久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

玩玩DriverWorks(二)

 李林俠圖書館 2011-12-12

玩玩DriverWorks(二)-讀寫數(shù)據(jù)

                                      

這兩天怎么老想玩DriverWorks!!!
今天抽了一個小時寫個小驅(qū)動練習(xí)一下KIrp和KMemory配合訪問三種IO方式中的數(shù)據(jù).KIrp是對IRP請求對象的包裝,它有很多成員函數(shù)用于操作IRP結(jié)構(gòu).

1.Buffered IO:
在Buffered IO方式中IO管理器會分配一塊堆內(nèi)存然后把用戶態(tài)緩沖區(qū)數(shù)據(jù)copy進(jìn)來再傳給驅(qū)動程序,而輸出時IO管理器會把堆內(nèi)存中的數(shù)據(jù)copy回用戶態(tài)緩沖區(qū).

我們使用下面這樣的代碼來得到輸入/輸出緩沖區(qū)和大小
KIrp I;
....

ULONG inputSize = I.IoctlInputBufferSize();
ULONG outputSize = I.IoctlOutputBufferSize();
   
PVOID inputBuffer = I.IoctlBuffer();
PVOID outputBuffer = I.IoctlBuffer();

一目了然吧!
我想要介紹一下這幾個函數(shù),但你實際上可以跳過下面的一小段因為用DriverWorks根本用不著知道這些細(xì)節(jié).

IoctlBuffer,IoctlInputBufferSize,IoctlOutputBufferSize函數(shù)實現(xiàn)非常簡單:
inline PVOID& KIrp::IoctlBuffer(void)
{
 return m_Irp->AssociatedIrp.SystemBuffer;
}

inline ULONG& KIrp::IoctlOutputBufferSize(EStackLocation s)
{
 ValidateStackLocation(s);

 if (s == CURRENT)
  return IoGetCurrentIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.OutputBufferLength;
 else
  return IoGetNextIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.OutputBufferLength;
}

inline ULONG& KIrp::IoctlInputBufferSize(EStackLocation s)
{
 ValidateStackLocation(s);

 if (s == CURRENT)
  return IoGetCurrentIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.InputBufferLength;
 else
  return IoGetNextIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.InputBufferLength;
}
在IoctlOutputBufferSize和IoctlInputBufferSize中S有一個默認(rèn)參數(shù)CURRENT,上面的代碼就是這樣調(diào)用它們的.可以看到其實是對IO_STACK_LOCATION結(jié)構(gòu)直接的操作.

2.Direct IO:
Direct IO方式中IO管理器分將用戶態(tài)緩沖區(qū)映射到核心態(tài)(地址不一樣,但其實是一塊內(nèi)存),并鎖定內(nèi)存不要分頁機(jī)制將內(nèi)存交換到外存中.然后IO管理器將緩沖區(qū)在核心態(tài)的的地址傳給驅(qū)動程序.Direct IO的分成METHOD_IN_DIRECT和METHOD_OUT_DIRECT

2.1 在METHOD_IN_DIRECT中我們使用這樣的代碼來訪問緩沖區(qū)及大小
KIrp I;
....

KMemory Mem(I.Mdl());
   
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG writeSize = I.WriteSize();
ULONG bytesSent = 0;

2.2 在METHOD_OUT_DIRECT中要像這樣來訪問緩沖區(qū)及大小
KIrp I;
....

KMemory Mem(I.Mdl());
   
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG readSize = I.ReadSize();
ULONG bytesRead = 0;

I.Mdl函數(shù)是這樣實現(xiàn)的:
inline PMDL& KIrp::Mdl(void)
{
 return m_Irp->MdlAddress;
}
它直接返回IRP結(jié)構(gòu)的MdlAddress字段,而MapToSystemSpace的實現(xiàn)代碼是這樣的:

inline PVOID KMemory::MapToSystemSpace(void)
{
 return GetSystemAddressForMdl(m_pMdl);
}

它調(diào)用下面這個函數(shù),這里我不太明白為什么不直接調(diào)用MmGetSystemAddressForMdl

inline PVOID GetSystemAddressForMdl(PMDL pMdl)
{
    CSHORT  canFail;   // original fail flag in MDL

    if(!(pMdl->MdlFlags &
            (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))) {

        // get the current fail flag
        canFail = (CSHORT)(pMdl->MdlFlags & MDL_MAPPING_CAN_FAIL);

        // set 'mapping can fail' so we don't bugcheck
        // if MmMapLockedPages fails
        pMdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;

        // try to map the buffer
        pMdl->MappedSystemVa =
            (PVOID)(((ULONG_PTR)MmMapLockedPages(pMdl, KernelMode)) |
                                MmGetMdlByteOffset(pMdl));

        // set the original flag back in the MDL
        if(!canFail) {
            pMdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
        }
    }

    return pMdl->MappedSystemVa;
}

3 Neither IO:
在Neither IO,IO管理器直接把用戶態(tài)的緩沖區(qū)地址和大小傳給驅(qū)動,不做任何處理.這是很危險的,通常情況下,我們需要寫一些小的助手驅(qū)動以進(jìn)入Ring0或是調(diào)用一些底層功能,如果可以肯定驅(qū)動的派遣函是運行在被動級并且在我們自己指定程序的進(jìn)程上下文里,那么用用這種方式也無所謂.除此以外盡可能不用這樣的IO方式.通常需要使用這樣的代碼來訪問緩沖區(qū)和大小:
KIrp I;
....

ULONG inputSize = I.IoctlInputBufferSize();
ULONG outputSize = I.IoctlOutputBufferSize();
   
PVOID inputBuffer = I.IoctlType3InputBuffer();
PVOID outputBuffer = I.UserBuffer();

IoctlType3InputBuffer和UserBuffer的實現(xiàn)代碼:
inline PVOID& KIrp::IoctlType3InputBuffer(EStackLocation s)
{
 ValidateStackLocation(s);

 if (s == CURRENT)
  return IoGetCurrentIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.Type3InputBuffer;
 else
  return IoGetNextIrpStackLocation(m_Irp)->
   Parameters.DeviceIoControl.Type3InputBuffer;
}

inline PVOID& KIrp::UserBuffer(void)
{
 return m_Irp->UserBuffer;
}

4. 現(xiàn)在可以總結(jié)一下,根據(jù)這些我們可以學(xué)到在DDK層面上應(yīng)該怎么操作這些IO方式中的緩沖區(qū):

4.1 在驅(qū)動的派遣函數(shù)中可以使用IoGetCurrentIrpStackLocation得到IO_STACK_LOCATION可以根據(jù)它的Control字段確定是什么派遣函數(shù)(因為可以將多個派遣函數(shù)地址指向一個派遣函數(shù)來處理多個請求).在Control等于IRP_MJ_DEVICE_CONTROL時來要根據(jù)DeviceIoControl的子字段IoControlCode來確定是什么控制代碼.

4.2 對于Buffered IO和Neither IO可以使用它的DeviceIoControl字段和三個子字段來訪問緩沖區(qū)和大小參數(shù):
typedef struct _IO_STACK_LOCATION {
....
union {
...
 struct {
      ULONG  OutputBufferLength;
      ULONG  InputBufferLength;
      ULONG  IoControlCode;
      PVOID  Type3InputBuffer;
    } DeviceIoControl;
...
 }
....
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;

4.3 對于Direct IO則要使用MmGetSystemAddressForMdl來將IRP結(jié)構(gòu)的MdlAddress(內(nèi)存描述表)字段映射到內(nèi)核地址空間并鎖定,得到一個內(nèi)核空間地址才能進(jìn)一步操作.Direct IO方式中的輸入輸出大小參數(shù)由IO_STACK_LOCATION的Read.Length和Write.Length指示

typedef struct _IO_STACK_LOCATION {
....
union {
...
 struct {
      ULONG  Length;
      ULONG  Key;
      LARGE_INTEGER  ByteOffset;
    } Read;
 
    struct {
      ULONG  Length;
      ULONG  Key;
      LARGE_INTEGER  ByteOffset;
    } Write;
...
 }
....
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;

說不看庫源代碼的又忍不住開始分析,呵呵!其實可以把DriverWorks的對象類搞清楚怎么用就可以了.如果是想順便把自己的DDK開發(fā)能力也提高一下的話,庫的源代碼也可以參考.

有了昨天的DriverWorks基本介紹,我想下面的代碼應(yīng)該不是很難懂吧!
//Interface.h
#ifndef __INTERFACE_H__
#define __INTERFACE_H__

#define DEVICE_NAME L"IoDemoDevice"
#define FILE_DEVICE_IODEMO 0x8000

#define IOCTL_DO_BUFFERED_IO \
 CTL_CODE(FILE_DEVICE_IODEMO,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_DO_DIRECT_IN \
 CTL_CODE(FILE_DEVICE_IODEMO,0x801,METHOD_IN_DIRECT,FILE_ANY_ACCESS)

#define IOCTL_DO_DIRECT_OUT \
 CTL_CODE(FILE_DEVICE_IODEMO,0x802,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)

#define IOCTL_DO_NEITHER_IO \
 CTL_CODE(FILE_DEVICE_IODEMO,0x803,METHOD_NEITHER,FILE_ANY_ACCESS)

#endif


//IODemo.cpp
#define VDW_MAIN
#define DRIVER_FUNCTION_UNLOAD

#define DRIVER_FUNCTION_CREATE
#define DRIVER_FUNCTION_CLOSE
#define DRIVER_FUNCTION_CLEANUP
#define DRIVER_FUNCTION_DEVICE_CONTROL

#include "vdw.h"
#include "Interface.h"

class IoDemoDriver:public KDriver
{
 SAFE_DESTRUCTORS;
public:
 virtual NTSTATUS DriverEntry(IN PUNICODE_STRING RegistryPath);
 virtual VOID Unload();
};

DECLARE_DRIVER_CLASS(IoDemoDriver,NULL)

class IoDemoDevice:public KDevice
{
 SAFE_DESTRUCTORS;
public:
 IoDemoDevice();
 DEVMEMBER_DISPATCHERS;
};

IoDemoDevice::IoDemoDevice():KDevice()
{
 if (!NT_SUCCESS(m_ConstructorStatus))
 {
  DbgPrint(__FUNCTION__": Failed to create device MyDevice");
  return;
 }
}

NTSTATUS IoDemoDevice::Create(KIrp I)
{
 DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);

 I.Information()=0;
 I.Complete(STATUS_SUCCESS);

 return STATUS_SUCCESS;
}

NTSTATUS IoDemoDevice::Close(KIrp I)
{
 DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);

 I.Information()=0;
 I.Complete(STATUS_SUCCESS);

 return STATUS_SUCCESS;
}

NTSTATUS IoDemoDevice::CleanUp(KIrp I)
{
 DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);

 I.Information()=0;
 I.Complete(STATUS_SUCCESS);

 return STATUS_SUCCESS;
}

NTSTATUS IoDemoDevice::DeviceControl(KIrp I)
{
 DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);

 switch(I.IoctlCode())
 {
 case IOCTL_DO_BUFFERED_IO:
  {
   DbgPrint(__FUNCTION__":IOCTL_DO_BUFFERED_IO\n",I);

   ULONG inputSize = I.IoctlInputBufferSize();
   ULONG outputSize = I.IoctlOutputBufferSize();
   
   PVOID inputBuffer = I.IoctlBuffer();
   PVOID outputBuffer = I.IoctlBuffer();

   //顯示出傳進(jìn)來的字符串
   if(inputSize)
    DbgPrint("inputBuffer:%s",(char*)inputBuffer);

   //返回一個字符串
   char chDoBufferedIO[]="DO_BUFFERED_IO";
   strncpy((char*)outputBuffer,chDoBufferedIO,outputSize);

   I.Information()=strlen(chDoBufferedIO);
  }
  break;

 case IOCTL_DO_DIRECT_IN:
  {
   DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_IN\n",I);
   KMemory Mem(I.Mdl());
   
   PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
   ULONG writeSize = I.WriteSize();
   ULONG bytesSent = 0;

   if(writeSize)
    DbgPrint("pBuffer:%s",(char*)pBuffer);

   I.Information()=0;
  }
  break;

 case IOCTL_DO_DIRECT_OUT:
  {
   DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_OUT\n",I);
   KMemory Mem(I.Mdl());
   
   PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
   ULONG readSize = I.ReadSize();
   ULONG bytesRead = 0;

   if(readSize)
   {
    char chDirectOut[]="DO_DIRECT_OUT";
    strncpy((char*)pBuffer,chDirectOut,readSize);
    I.Information()=strlen(chDirectOut);
   }
  }
  break;

 case IOCTL_DO_NEITHER_IO:
  {
   DbgPrint(__FUNCTION__":IOCTL_DO_NEITHER_IO\n",I);
   ULONG inputSize = I.IoctlInputBufferSize();
   ULONG outputSize = I.IoctlOutputBufferSize();
   
   PVOID inputBuffer = I.IoctlType3InputBuffer();
   PVOID outputBuffer = I.UserBuffer();

   //顯示出傳進(jìn)來的字符串
   if(inputSize)
    DbgPrint("inputBuffer:%s",(char*)inputBuffer);

   //返回一個字符串
   char chDoNeitherIo[]="DO_NEITHER_IO";
   strncpy((char*)outputBuffer,chDoNeitherIo,outputSize);

   I.Information()=strlen(chDoNeitherIo);
  }
  break;

 default:
  I.Information()=0;
  I.Complete(STATUS_INVALID_DEVICE_REQUEST);
  return STATUS_INVALID_DEVICE_REQUEST;
 }

 I.Complete(STATUS_SUCCESS);
 
 return STATUS_SUCCESS;
}

NTSTATUS IoDemoDriver::DriverEntry(IN PUNICODE_STRING RegistryPath)
{
 NTSTATUS status = STATUS_SUCCESS;

 DbgPrint(__FUNCTION__":RegistryPath:%S\n",RegistryPath->Buffer);

 IoDemoDevice* pDevice = new (
   DEVICE_NAME,
   FILE_DEVICE_UNKNOWN,
   DEVICE_NAME,
   0,
   DO_DIRECT_IO
   )
  IoDemoDevice();

 if (pDevice == NULL)
 {
  status = STATUS_INSUFFICIENT_RESOURCES;
 }
 else
 {
  status = pDevice->ConstructorStatus();
  if (!NT_SUCCESS(status))
  {
   delete pDevice;
  }
  else
   DbgPrint(__FUNCTION__":Created IoDemoDevice!\n");
 }

 return status;
}

VOID IoDemoDriver::Unload()
{
 DbgPrint(__FUNCTION__);
 
 KDriver::Unload();
}

最后可以用我的小工具測試一下,,Load驅(qū)動后可以點Content按鈕編輯數(shù)據(jù)包,,也可以查看驅(qū)動返回的數(shù)據(jù),,顯示方式是十六進(jìn)制,注意根據(jù)IO控制代碼的定義選擇不同的Method,DeviceId和ControlCode組合方式.個人感覺這個小工具還是比較好用的,,呵呵!

【作者: kruglinski】【訪問統(tǒng)計:

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多