Windows 驱动开发笔记(六)

来源:互联网 发布:阿里云服务器上传文件 编辑:程序博客网 时间:2024/06/11 21:30

 Windows 驱动开发笔记(六)
一个驱动程序是要能操作硬件的。那么,操作硬件就要能够操作设备的端口和特定的内存映射等。在windows nt设计时为了避免为兼容各种平台而使用大量条件编译代码,Windows NT的设计者发明了硬件抽象层(HAL),HAL提供了用于访问端口和内存资源的函数。而不是使用_inp(),_outp()等函数直接来操作端口。下面我们来使用写一个用PC喇叭法声的例子。
  WRITE_PORT_UCHAR((PUCHAR)0x43,(UCHAR)0xb6);//设置定时器
  WRITE_PORT_UCHAR((PUCHAR)0x42,(UCHAR)0x12);//设置发声频率
  WRITE_PORT_UCHAR((PUCHAR)0x42,(UCHAR)0x10);//设置发声频率
  WRITE_PORT_UCHAR((PUCHAR)0x61,(UCHAR)(READ_PORT_UCHAR((PUCHAR)0x61)|(UCHAR)0x3));//开启设备

  WRITE_PORT_UCHAR((PUCHAR)0x61,(UCHAR)(READ_PORT_UCHAR((PUCHAR)0x61)&(UCHAR)0xfc));//关闭设备

我们把这些代码加入驱动中.

hello.c 文件


#ifndef __HELLOWORLD_C__
#define __HELLOWORLD_C__

#define DEBUGMSG

#include "Hello.h"

//驱动入口
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS ntStatus=STATUS_SUCCESS;
    PDEVICE_OBJECT lpDeviceObject=NULL;   //指向设备对象的指针
    UNICODE_STRING DeviceNameString;      //设备名称
    UNICODE_STRING DeviceLinkString;      //符号连接

    //调试信息
    #ifdef DEBUGMSG
           DbgPrint("Starting DriverEntry()/n");
    #endif

    RtlInitUnicodeString(&DeviceNameString,NT_DEVICE_NAME);  //初始化Unicode字符串

    //创建设备
    ntStatus=IoCreateDevice(DriverObject,0,&DeviceNameString,FILE_DEVICE_UNKNOWN,
                            0,FALSE,&lpDeviceObject);

    lpDeviceObject->Flags |= DO_BUFFERED_IO; //定义使用缓冲方式
 
 //使用NT_SUCCESS宏检测函数调用是否成功
    if (!NT_SUCCESS(ntStatus))
    {
        #ifdef DEBUGMSG
               DbgPrint("Error IoCreateDevice()/n");
        #endif
        goto Error;
    }

    RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);

    //创建符号连接
    ntStatus=IoCreateSymbolicLink(&DeviceLinkString,&DeviceNameString);

    if (!NT_SUCCESS(ntStatus))
    {
        #ifdef DEBUGMSG
               DbgPrint("Error IoCreateSymbolicLink()/n");
        #endif
        goto Error;
    }

    //设置IRP派遣例程和卸载例程
    DriverObject->MajorFunction[IRP_MJ_CREATE]=HelloCreateDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]=HelloCloseDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloControlDispatch;
    DriverObject->DriverUnload=HelloWorldUnLoad;

    return ntStatus;

    Error:
          #ifdef DEBUGMSG
                 DbgPrint("Error DriverEntry()/n");
          #endif

          return ntStatus;
}
//打开设备例程
NTSTATUS HelloCreateDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
    NTSTATUS ntStatus=STATUS_SUCCESS;
    ULONG IoControlCodes=0;             //I/O控制代码
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈

    //设置IRP状态
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information=0;

    #ifdef DEBUGMSG
           DbgPrint("Starting HelloCreateDispatch()/n");
    #endif

    IrpStack=IoGetCurrentIrpStackLocation(pIrp);    //得到当前调用者的IRP
    #ifdef DEBUGMSG
           DbgPrint("IRP_MJ_CREATE/n");
    #endif
 ntStatus=pIrp->IoStatus.Status;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return ntStatus;
}
//关闭例程
NTSTATUS HelloCloseDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
    NTSTATUS ntStatus=STATUS_SUCCESS;
    ULONG IoControlCodes=0;             //I/O控制代码
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈

    //设置IRP状态
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information=0;

    #ifdef DEBUGMSG
           DbgPrint("Starting HelloCloseDispatch()/n");
    #endif

    IrpStack=IoGetCurrentIrpStackLocation(pIrp); //得到当前调用者的IRP

    #ifdef DEBUGMSG
           DbgPrint("IRP_MJ_CLOSE/n");
    #endif

 ntStatus=pIrp->IoStatus.Status;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return ntStatus;
}
//控制例程
NTSTATUS HelloControlDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
    NTSTATUS ntStatus=STATUS_SUCCESS;
    ULONG IoControlCodes=0;             //I/O控制代码
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈
 PVOID pInputBuffer,pOutputBuffer;  //缓冲区指针
 ULONG inputLength,outputLength;   //缓冲区长度
 PCHAR pReturnData = "IOCTL - Buffered I/O From Kernel!";
 ULONG  dwDataSize = sizeof("Example_ReadDirectIO - Hello from the Kernel!");

    //设置IRP状态
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information=0;

   
 
 #ifdef DEBUGMSG
           DbgPrint("Starting HelloControlDispatch()/n");
    #endif

 
 IrpStack=IoGetCurrentIrpStackLocation(pIrp);    //得到当前调用者的IRP堆栈
  
 //取得I/O控制代码
    IoControlCodes=IrpStack->Parameters.DeviceIoControl.IoControlCode;

 switch (IoControlCodes)
 {
    //启动
       case START_HELLPWORLD:
            DbgPrint("Starting /"Hello World/"/n");
   WRITE_PORT_UCHAR((PUCHAR)0x43,(UCHAR)0xb6);
   WRITE_PORT_UCHAR((PUCHAR)0x42,(UCHAR)0x12);
   WRITE_PORT_UCHAR((PUCHAR)0x42,(UCHAR)0x10);
   WRITE_PORT_UCHAR((PUCHAR)0x61,(UCHAR)(READ_PORT_UCHAR((PUCHAR)0x61)|(UCHAR)0x3));
   break;
       //停止
       case STOP_HELLPWORLD:
            DbgPrint("Stoping /"Hello World/"/n");
            WRITE_PORT_UCHAR((PUCHAR)0x61,(UCHAR)(READ_PORT_UCHAR((PUCHAR)0x61)&(UCHAR)0xfc));
   break;
    case WRITE_HELLPWORLD:
            inputLength  = IrpStack->Parameters.DeviceIoControl.InputBufferLength;  //IRP堆栈中得到长度
      pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;//IRP中得到地址
    
         DbgPrint("Reading a Buffer Data!/n");
   if(pInputBuffer)
   {             
    DbgPrint("COMM_BufferedIo UserModeMessage = '%s'/n", pInputBuffer);
   }
   break;
    case READ_HELLPWORLD:
            outputLength  = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;  //IRP堆栈中得到长度
      pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;//IRP中得到地址
            DbgPrint("Writing a Buffer Data!/n");
   if(pOutputBuffer)
   {             
    
    RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
    pIrp->IoStatus.Information=dwDataSize;
   }
   break;

    default:
       DbgPrint("Invalid Parameter /"Hello World/"/n");
            pIrp->IoStatus.Status=STATUS_INVALID_PARAMETER;
            break;
    }

 ntStatus=pIrp->IoStatus.Status;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return ntStatus;
}

VOID HelloWorldUnLoad (IN PDRIVER_OBJECT DriverObject)
{
     UNICODE_STRING DeviceLinkString;
     PDEVICE_OBJECT DeviceObjectTemp1=NULL;
     PDEVICE_OBJECT DeviceObjectTemp2=NULL;

     #ifdef DEBUGMSG
            DbgPrint("Starting HelloWorldUnLoad()/n");
     #endif

     RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);
     IoDeleteSymbolicLink(&DeviceLinkString);  //删除符号连接

     if (DriverObject)
     {
         DeviceObjectTemp1=DriverObject->DeviceObject;

         //删除设备
         while (DeviceObjectTemp1)
         {
                DeviceObjectTemp2=DeviceObjectTemp1;
                DeviceObjectTemp1=DeviceObjectTemp1->NextDevice;
                IoDeleteDevice(DeviceObjectTemp2);
         }
     }
}

#endif

 

hello.h 文件


#ifndef __HELLOWORLD_H__
#define __HELLOWORLD_H__

#include <ntddk.h>

#define DEVICE_HELLO_INDEX 0x860

#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define STOP_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define WRITE_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+2,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define READ_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+3,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define NT_DEVICE_NAME L"//Device//hello"        //设备名称
#define DOS_DEVICE_NAME L"//DosDevices//hello"   //符号连接

NTSTATUS HelloCreateDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS HelloCloseDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS HelloControlDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);

VOID HelloWorldUnLoad (IN PDRIVER_OBJECT DriverObject);

#endif


helloctl.c 文件


#define DEBUGMSG

#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

#define DEVICE_HELLO_INDEX 0x860

#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define STOP_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define WRITE_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+2,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define READ_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+3,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define erron GetLastError()

#define MY_DEVICE_NAME "////.//hello"

#define MY_DEVICE_START "-start"
#define MY_DEVICE_STOP "-stop"
#define MY_DEVICE_WRITE "-input"
#define MY_DEVICE_READ "-output"

#define MY_INPUT_BUF_SIZE 255
#define MY_OUTPUT_BUF_SIZE 255

BOOL DriverControl (TCHAR *Maik);

void Usage (TCHAR *Paramerter);

int main (int argc,TCHAR *argv[])
{
    if (argc!=2)
    {
        Usage(argv[0]);
        return 0;
    }

    if (strcmpi(argv[1],MY_DEVICE_START)==0 || strcmpi(argv[1],MY_DEVICE_STOP)==0
  || strcmpi(argv[1],MY_DEVICE_WRITE)==0 || strcmpi(argv[1],MY_DEVICE_READ)==0)
        DriverControl(argv[1]);
    else
    {
        Usage(argv[0]);
        return 0;
    }

    return 0;
}

BOOL DriverControl (TCHAR *Maik)
{
    
  HANDLE hDevice=NULL;  //设备句柄
     DWORD RetBytes=0;
  char  inputBuffer[MY_INPUT_BUF_SIZE]; //输出用户缓冲区
  char  outputBuffer[MY_OUTPUT_BUF_SIZE];//输入用户缓冲区
     //获得设备句柄
     hDevice=CreateFile(MY_DEVICE_NAME,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

     if (hDevice==INVALID_HANDLE_VALUE)
     {
         #ifdef DEBUGMSG
                printf("CreateFile() GetLastError reports %d/n",erron);
         #endif
         return FALSE;
     }

     //启动
     if (strcmpi(Maik,MY_DEVICE_START)==0)
     {
         //传递启动的I/O控制代码
         if (!(DeviceIoControl(hDevice,START_HELLPWORLD,NULL,0,NULL,0,&RetBytes,NULL)))
         {
             #ifdef DEBUGMSG
                    printf("DeviceIoControl() GetLastError reports %d/n",erron);
             #endif
             CloseHandle(hDevice);
             return FALSE;
         }
     }

     //停止
     if (strcmpi(Maik,MY_DEVICE_STOP)==0)
     {
   //传递停止的I/O控制代码
         if (!(DeviceIoControl(hDevice,STOP_HELLPWORLD,NULL,0,NULL,0,&RetBytes,NULL)))
         {
             #ifdef DEBUGMSG
                    printf("DeviceIoControl() GetLastError reports %d/n",erron);
             #endif
             CloseHandle(hDevice);
             return FALSE;
         }
     }


  //输入数据
     if (strcmpi(Maik,MY_DEVICE_WRITE)==0)
     {
         //输入数据缓冲区
         strcpy(inputBuffer,"Hello,Input Data!");
   if (!(DeviceIoControl(hDevice,WRITE_HELLPWORLD,&inputBuffer,MY_INPUT_BUF_SIZE,NULL,0,&RetBytes,NULL)))
         {
             #ifdef DEBUGMSG
                    printf("DeviceIoControl() GetLastError reports %d/n",erron);
             #endif
             CloseHandle(hDevice);
             return FALSE;
         }
     }

  //输出数据
  if (strcmpi(Maik,MY_DEVICE_READ)==0)
     {
   if (!(DeviceIoControl(hDevice,READ_HELLPWORLD,NULL,0,&outputBuffer,MY_OUTPUT_BUF_SIZE,&RetBytes,NULL)))
         {
             #ifdef DEBUGMSG
                    printf("DeviceIoControl() GetLastError reports %d/n",erron);
             #endif
             CloseHandle(hDevice);
             return FALSE;
         }else{
  
    printf("DeviceIoControl() output Data! s=%s/n return Bytes=%d%/n",outputBuffer,RetBytes);
  
   }
     }
 
  if (hDevice)
         CloseHandle(hDevice);  //关闭句柄

     return TRUE;
}

void Usage (TCHAR *Paramerter)
{
     fprintf(stderr,"============================================================================/n"
             "      Hello驱动控制例程/n"
             "%s -start/t启动/n"
             "%s -stop /t停止/n"
      "%s -input/t输入/n"
      "%s -output/t输入/n"
             "本程序只是用做代码交流,如有错误,还请多多包含!/n"
             "============================================================================/n"
             ,Paramerter,Paramerter,Paramerter);
}

安装驱动.
使用
>helloctl -start  开启
>helloctl -stop   关闭

 

原创粉丝点击