YJX_Driver_028_实战EXE和SYS通信(缓冲模式)

1、

实战EXE和SYS通信
  A、用户层传入数据-EXE部分代码
  B、驱动层接收数据并处理-SYS部分代码
  C、驱动层返回数据至用户层
  D、用户层获得处理结果

【190】假设驱动部分已经按照我们的思路写好了

【305】创建 VC6 Win32ConsoleApplication 名称为:"test_exe"

  【345】选择的是“A "Hello, World" application”,非“An empty project”

【400】写代码(应用层的):

  【1290】sys和exe 都需要使用 CTL_CODE来构建 控制码,于是新建一个头文件ctl_code.h,【1415】将 CTL_CODE 相关的(宏)代码写在这个头文件里面

#include <winioctl.h> // CTL_CODE
#define add_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define sub_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

 

#include <windows.h>
#include "ctl_code.h"
int port[2],bufret;
DWORD dwWrite;
int add(HANDLE hDevice,int a,int b)
{
  port[0]=a;
  port[1]=b;
  DeviceIoControl(hDevice, add_code , &port, 8, &bufret, 4, &dwWrite, NULL);
  return bufret;
}


int main(int argc, char* argv[])
{
  //CreateFile hDevice
  HANDLE hDevice = CreateFile(
    "\\\\.\\My_DriverLinkName", // \\??\\My_DriverLinkName
    GENERIC_READ | GENERIC_WRITE,
    0, // share mode none
    NULL, // no security
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL ); // no template

  printf("start\n");
  if (hDevice == INVALID_HANDLE_VALUE)
  {
    printf("获取驱动句柄失败: %s with Win32 error code: %d\n","MyDriver",
    GetLastError() );
    getchar(); // system("pause");
    return -1;
  }
  //add_code
  int a=55;
  int b=33;
  int r= add(hDevice, a, b);
  printf("%d+%d=%d\n", a, b, r);
  getchar();
  return 0;
}

【2585】驱动层的代码,以 第25课 的代码为例,进行一些修改

  【2780】修改符号链接

    RtlInitUnicodeString(&symLinkName,L"\\??\\My_DriverLinkName");

  【3615】把 刚才 exe项目里面创建的头文件ctl_code.h 复制到 sys项目中 

  【3935】复制过来的 ctl_code.h 中,要把 “#include <winioctl.h>”注释掉,或者 更通用的做法 这里我们就不讲了...

    【3980】在 NTDDK.h 里面已经有了 CTL_CODE的定义(ZC: 可以用 “#ifdef” 来控制是否需要include winioctl.h/NTDDK.h,也可以将 include winioctl.h/NTDDK.h 写在 ctl_code.h的外面)

   【4625】ZC: 看到 sys中 输入/输出 缓冲区的获取,都是“pIrp->AssociatedIrp.SystemBuffer” ! ! ! 它会自动映射相应的内存?读的时候就用DeviceIoControl的输入缓冲区,写的时候就用DeviceIoControl的输出缓冲区?

#include "ctl_code.h"

NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj, IN PIRP pIrp)
{
  ULONG info;
  //得到当前栈指针
  PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
  ULONG mf=stack->MajorFunction; // 区分IRP
  switch (mf)
  {
    case IRP_MJ_DEVICE_CONTROL:
    {
      KdPrint(("Enter myDriver_DeviceIOControl\n"));
      NTSTATUS status = STATUS_SUCCESS;

      //得到输入缓冲区大小
      ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
      //得到输出缓冲区大小
      ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
      //得到IOCTL码
      ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
      switch (code)
      {
        case add_code:
        {
          int a,b;
          KdPrint(("add_code 1111111111111111111\n"));
          //缓冲区方式IOCTL
          //获取缓冲区数据 a,b
          int * InputBuffer = (int*) pIrp->AssociatedIrp.SystemBuffer;
          _asm
          {
            mov eax,InputBuffer
            mov ebx,[eax]
            mov a,ebx
            mov ebx,[eax+4]
            mov b,ebx
          }
          KdPrint(("a=%d,b=%d \n", a,b));

          a=a+b;
          //C、驱动层返回数据至用户层
          //操作输出缓冲区
          int* OutputBuffer = (int*) pIrp->AssociatedIrp.SystemBuffer;
          _asm
          {
            mov eax,a
            mov ebx,OutputBuffer
            mov [ebx],eax
          }
          KdPrint(("a+b=%d \n",a));

          //设置实际操作输出缓冲区长度
          info = 4;
          break;
        }
        case sub_code:
        {
          break;
        }
      }// switch (code)
      break;
    } // IRP_MJ_DEVICE_CONTROL
    case IRP_MJ_CREATE:
    {
      break;
    }
    case IRP_MJ_CLOSE:
    {
      break;
    }
    case IRP_MJ_READ:
    {
      break;
    }
  }

  //对相应的IPR进行处理
  pIrp->IoStatus.Information = info;//设置操作的字节数为0,这里无实际意义
  pIrp->IoStatus.Status = STATUS_SUCCESS;//返回成功
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);//指示完成此IRP
  KdPrint(("离开派遣函数\n"));//调试信息
  return STATUS_SUCCESS; //返回成功
}

 

【5280】sys 和 exe 放到 虚拟机中,进行测试

  【5455】此时运行,exe计算得到了错误的结果,∵变量未初始化(ZC: 貌似不对啊,exe能打开驱动,说明已经存在了相关的符号链接了啊)

  【5495】载入驱动

    【5535】此时 exe的计算结果还是错误的,可能是刚才已经载入了驱动。先卸载 之前打开的驱动

  【5640】此时 报错 获取句柄失败。蓝屏 重新测试

  【5745】exe计算结果 还是错误的

 

【5760】改代码 加调试信息

【6250】卸载例程 中的 符号链接名称 是错误的 没有改过来

【6855】可能是卸载的时候卸载的不干净,点击 DriverMonitor的"STOP"按钮 虚拟机会蓝屏

 

2、



posted @ 2016-04-07 16:34  DebugSkill  阅读(171)  评论(0编辑  收藏  举报