驱动学习5

5.1.2 

直接看PAGE_SIZE的大小就可以知道当前分页的大小

//
// Define the page size
//

#define PAGE_SIZE 0x2000

5.1.4

驱动程序的不同函数运行在不同的进程中,DriverEntry和AddDevice函数是运行在系统进程中的(system)

3: kd> !process sysmtem
PROCESS 8a52a830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 0aac0020  ObjectTable: e1003e00  HandleCount: 265.
PsGetCurrentProcess可以获得当前线程所在的进程指针(指向EPROCESS)

可以用windbg查看这个:偏移量为0x174

   +0x174 ImageFileName    : [16]  "System"
所以可以这样获取:

#pragma PAGEDCODE
VOID DisplayItsProcessName()
{
	PEPROCESS pEProcess = PsGetCurrentProcess();
	PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
	KdPrint(("%s
",ProcessName));
}

5.1.5

当程序的中断请求级在DISPATCH_LEVEL上(包括),程序只能使用非分页内存,否则将蓝屏

堆中申请内存函数:

PVOID 
  ExAllocatePool(
    IN POOL_TYPE  PoolType,
    IN SIZE_T  NumberOfBytes
    );

对应释放内存函数:

VOID 
  ExFreePool(
    IN PVOID  P
    );


5.1.6 

双向链表结构中,都需要包含LIST_ENTRY,但不一定在结构的首位,所以DDK提供了一个宏

整个结构体的首地址=LIST_ENTRY的地址-LIST_ENTRY在整个结构体中的相对偏移

#define CONTAINING_RECORD(address, type, field) ((type *)( 
                                                  (PCHAR)(address) - 
                                                  (ULONG_PTR)(&((type *)0)->field)))
// 从尾部删除一个元素
		typedef struct _MYDATASTRUCT 
		{
			ULONG number;
			LIST_ENTRY ListEntry1;
		} MYDATASTRUCT, *PMYDATASTRUCT;
		PLIST_ENTRY pEntry = RemoveTailList(&linkListHead);
		pData = CONTAINING_RECORD(pEntry, MYDATASTRUCT, ListEntry1);
为了简明示例,特别把LIST_ENTRY的元素名叫个ListEntry1

5.3 Lookaside结构

如果驱动需要频繁从内存中申请,回收固定大小的内存,DDK提供了Lookaside对象来解决这个问题


5.4内存系列函数

内存复制(非重叠)

VOID 
  RtlCopyMemory(
    IN VOID UNALIGNED  *Destination,
    IN CONST VOID UNALIGNED  *Source,
    IN SIZE_T  Length
    );

内存复制(可重叠),函数内部对两个内存是否重叠进行了判断,这种判断牺牲了速度

void RtlMoveMemory(
  __in          PVOID Destination,
  __in          const VOID* Source,
  __in          SIZE_T Length
);


填充内存

void RtlFillMemory(
  [out]                PVOID Destination,
  [in]                 SIZE_T Length,
  [in]                 BYTE Fill
);

内存置0

VOID 
  RtlZeroMemory(
    IN VOID UNALIGNED  *Destination,
    IN SIZE_T  Length
    );

内存比较

ULONG
  RtlEqualMemory( 
    CONST VOID  *Source1, 
    CONST VOID  *Source2, 
    SIZE_T  Length 
    );

DDK提供的标准的运行时函数名都是RtlXX形式,其中,大部分是以宏的形式给出,来自wdm.h:

#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length)))
#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))
#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))
#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))

5.6数据类型

DDK提供了一种新的64位整数的表示方式即

typedef union _LARGE_INTEGER {
    struct {
        ULONG LowPart;
        LONG HighPart;
    } DUMMYSTRUCTNAME;
    struct {
        ULONG LowPart;
        LONG HighPart;
    } u;
#endif //MIDL_PASS
    LONGLONG QuadPart;
} LARGE_INTEGER;
需要注意的是他是一个联合体,可以认为是LARGE_INTEGER的三个定义


5.6.3.

检测内存是否可读可写,在ring3用的是

IsBadReadPtr
IsBadWritePtr

在ring0用的是ProbeForRead和ProbeForWrite













原文地址:https://www.cnblogs.com/hgy413/p/3693357.html