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\n",ProcessName));
}
5.1.5
当程序的中断请求级在DISPATCH_LEVEL上(包括),程序只能使用非分页内存,否则将蓝屏
堆中申请内存函数:
PVOID
ExAllocatePool(
IN POOL_TYPE PoolType,
IN SIZE_T NumberOfBytes
);
对应释放内存函数:
VOID
ExFreePool(
IN PVOID P
);
双向链表结构中,都需要包含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