Windows驱动编程基础教程-谭文-代码整理
基本上是教程上原代码照抄,只给代码做了个排列组合,改了一些作者的小笔误
代码全部测试通过,测试环境:WinDDK 7600.16385.0 chk x86 WXP
教程上有很详细非常详细的讲解,偶就偷懒不写注释了
代码中有些应该考虑应该实现的东西偶不会,就省了。。。不会完善,能跑就行。。。
1 字符串使用
2 内存的分配与释放
3 LIST_ENTRY
4 LARGE_INTEGER
5 KSPIN_LOCK
6 文件操作
7 注册表读写
8 时间与定时
未完待续。。。
makefile
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def
sources
TARGETNAME=study
TARGETPATH=OBJ
TARGETTYPE=DRIVER
SOURCES= study.c
1 字符串使用
/*
*《Windows驱动编程基础教程-谭文》-字符串使用
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
DRIVER_UNLOAD StudyUnload;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
DriverObject->DriverUnload = StudyUnload;
return STATUS_SUCCESS;
}
VOID StudyUnload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING str1;
UNICODE_STRING dst;
WCHAR dst_buf[256];
UNICODE_STRING src = RTL_CONSTANT_STRING(L"source string"); //Init a UNICODE_STRING
NTSTATUS status;
PAGED_CODE();
DbgPrint("Study:Our driver is unloading\r\n");
//Init a UNICODE_STRING
RtlInitUnicodeString(&str1,L"Init the string str1");
KdPrint(("Init a UNICODE_STRING:%wZ\r\n",&str1));
//把dst初始化成拥有缓冲区长度为256的UNICODE_STRING空串
//!!! copy 之前一定要先给dst分配空间!!!
RtlInitEmptyUnicodeString(&dst,dst_buf,256*sizeof(WCHAR));
//copy a UNICODE_STRING
RtlCopyUnicodeString(&dst,&src);
KdPrint(("Copy a UNICODE_STRING:%wZ\r\n",&dst));
//append a UNICODE_STRING
status = RtlAppendUnicodeToString(&dst,L"|append string.");
KdPrint(("Append a UNICODE_STRING:%wZ\r\n",&dst));
return;
}
2 内存的分配与释放
/*
*《Windows驱动编程基础教程-谭文》-内存的分配与释放
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
//定义一个内存分配标记
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
DriverObject->DriverUnload = StudyUnload;
return STATUS_SUCCESS;
}
VOID StudyUnload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING dst = {0};
UNICODE_STRING src = RTL_CONSTANT_STRING(L"source string");
NTSTATUS status;
PAGED_CODE();
//根据src的长度,分配空间给dst
dst.Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool, //PoolTape
src.Length, //NumberOfBytes
MEM_TAG); //Tag
if(dst.Buffer == NULL){
status = STATUS_INSUFFICIENT_RESOURCES;
KdPrint(("FAIL with ExAllocatePoolWithTag"));
return;
}
dst.Length = dst.MaximumLength = src.Length;
RtlCopyUnicodeString(&dst,&src); //return void
KdPrint(("Copy a UNICODE_STRING:%wZ\r\n",&dst));
ExFreePool(dst.Buffer);
dst.Buffer = NULL;
dst.Length = dst.MaximumLength = 0;
return;
}
3 LIST_ENTRY
/*
*《Windows驱动编程基础教程-谭文》- LIST_ENTRY
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
//our list head
LIST_ENTRY my_list_head;
//our list node
typedef struct {
LIST_ENTRY list_entry; //simple to put it at the head of the struct
PFILE_OBJECT file_object;
UNICODE_STRING file_name;
int file_length;
}MY_FILE_INFOR,*PMY_FILE_INFOR;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
//Init our list head
InitializeListHead(&my_list_head);
DriverObject->DriverUnload = StudyUnload;
return STATUS_SUCCESS;
}
//Append a node to list, note that file_name is allocated outside
NTSTATUS StudyAppendNode(
PFILE_OBJECT file_object,
UNICODE_STRING file_name,
int file_length)
{
PMY_FILE_INFOR my_file_infor = (PMY_FILE_INFOR)ExAllocatePoolWithTag(PagedPool,sizeof(MY_FILE_INFOR),MEM_TAG);
if(my_file_infor == NULL){
return STATUS_INSUFFICIENT_RESOURCES;
}
my_file_infor->file_object = file_object;
my_file_infor->file_name = file_name;
my_file_infor->file_length = file_length;
InsertHeadList(&my_list_head, //PLIST_ENTRY ListHead,
(PLIST_ENTRY)my_file_infor); //PLIST_ENTRY Entry ==my_file_info->list_entry
//we put the LIST_ENTRY at the head of the struct,so my_file_info==my_file_info->list_entry here
return STATUS_SUCCESS;
}
VOID StudyUnload(PDRIVER_OBJECT DriverObject)
{
PFILE_OBJECT file_object = NULL;
UNICODE_STRING file_name = RTL_CONSTANT_STRING(L"c:\\study.txt");
UNICODE_STRING file_name2 = RTL_CONSTANT_STRING(L"c:\\study2.txt");
int file_length = 0x123;
PLIST_ENTRY p;
StudyAppendNode(file_object,file_name,file_length);
StudyAppendNode(file_object,file_name2,file_length);
for(p = my_list_head.Flink; p != &my_list_head.Flink; p = p->Flink){
PMY_FILE_INFOR elem = CONTAINING_RECORD(p, //Address
MY_FILE_INFOR, //Type
list_entry); //Field
KdPrint(("node of MY_FILE_INFOR list, name: %wZ\n",&elem->file_name));
}
return;
}
4 LARGE_INTEGER
/*
*《Windows驱动编程基础教程-谭文》- LARGE_INTEGER
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
//our list head
LIST_ENTRY my_list_head;
//our list node
typedef struct {
LIST_ENTRY list_entry; //simple to put it at the head of the struct
PFILE_OBJECT file_object;
UNICODE_STRING file_name;
LARGE_INTEGER file_length;
}MY_FILE_INFOR,*PMY_FILE_INFOR;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
//Init our list head
InitializeListHead(&my_list_head);
DriverObject->DriverUnload = StudyUnload;
return STATUS_SUCCESS;
}
//Append a node to list, note that file_name is allocated outside
NTSTATUS StudyAppendNode(
PFILE_OBJECT file_object,
UNICODE_STRING file_name,
LARGE_INTEGER file_length)
{
PMY_FILE_INFOR my_file_infor = (PMY_FILE_INFOR)ExAllocatePoolWithTag(PagedPool,sizeof(MY_FILE_INFOR),MEM_TAG);
if(my_file_infor == NULL){
return STATUS_INSUFFICIENT_RESOURCES;
}
my_file_infor->file_object = file_object;
my_file_infor->file_name = file_name;
my_file_infor->file_length = file_length;
InsertHeadList(&my_list_head, //PLIST_ENTRY ListHead,
(PLIST_ENTRY)my_file_infor); //PLIST_ENTRY Entry ==my_file_info->list_entry
//we put the LIST_ENTRY at the head of the struct,so my_file_info==my_file_info->list_entry here
return STATUS_SUCCESS;
}
VOID StudyUnload(PDRIVER_OBJECT DriverObject)
{
PFILE_OBJECT file_object = NULL;
UNICODE_STRING file_name = RTL_CONSTANT_STRING(L"c:\\study.txt");
UNICODE_STRING file_name2 = RTL_CONSTANT_STRING(L"c:\\study2.txt");
LARGE_INTEGER file_length1,file_length2;
PLIST_ENTRY p;
file_length1.QuadPart = 100;
file_length2.QuadPart = file_length1.QuadPart * 100;
StudyAppendNode(file_object,file_name,file_length1);
StudyAppendNode(file_object,file_name2,file_length2);
for(p = my_list_head.Flink; p != &my_list_head.Flink; p = p->Flink){
PMY_FILE_INFOR elem = CONTAINING_RECORD(p, //Address
MY_FILE_INFOR, //Type
list_entry); //Field
KdPrint(("node of MY_FILE_INFOR list, name: %wZ, length:%d\n",&elem->file_name,elem->file_length.QuadPart));
if(elem->file_length.QuadPart > 1000){
KdPrint(("file length > 1000,LowPart = %d, HighPart = %d\n",elem->file_length.LowPart,elem->file_length.HighPart));
}
}
return;
}
5 KSPIN_LOCK
/*
*《Windows驱动编程基础教程-谭文》- kSPIN_LOCK
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
//our list head
LIST_ENTRY my_list_head;
//our list node
typedef struct {
LIST_ENTRY list_entry; //simple to put it at the head of the struct
PFILE_OBJECT file_object;
UNICODE_STRING file_name;
LARGE_INTEGER file_length;
}MY_FILE_INFOR,*PMY_FILE_INFOR;
//our spin lock, CANNOT be local
KSPIN_LOCK my_spin_lock;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
//Init our list head
InitializeListHead(&my_list_head);
//Init our spin lock
KeInitializeSpinLock(&my_spin_lock);
DriverObject->DriverUnload = StudyUnload;
return STATUS_SUCCESS;
}
//Append a node to list, note that file_name is allocated outside
NTSTATUS StudyAppendNode(
PFILE_OBJECT file_object,
UNICODE_STRING file_name,
LARGE_INTEGER file_length)
{
PMY_FILE_INFOR my_file_infor = (PMY_FILE_INFOR)ExAllocatePoolWithTag(PagedPool,sizeof(MY_FILE_INFOR),MEM_TAG);
if(my_file_infor == NULL){
return STATUS_INSUFFICIENT_RESOURCES;
}
my_file_infor->file_object = file_object;
my_file_infor->file_name = file_name;
my_file_infor->file_length = file_length;
ExInterlockedInsertHeadList(&my_list_head, //PLIST_ENTRY ListHead,
(PLIST_ENTRY)my_file_infor,
&my_spin_lock);
return STATUS_SUCCESS;
}
VOID StudyUnload(PDRIVER_OBJECT DriverObject)
{
PFILE_OBJECT file_object = NULL;
UNICODE_STRING file_name = RTL_CONSTANT_STRING(L"c:\\study.txt");
UNICODE_STRING file_name2 = RTL_CONSTANT_STRING(L"c:\\study2.txt");
LARGE_INTEGER file_length1,file_length2;
PLIST_ENTRY p;
file_length1.QuadPart = 100;
file_length2.QuadPart = file_length1.QuadPart * 100;
StudyAppendNode(file_object,file_name,file_length1);
StudyAppendNode(file_object,file_name2,file_length2);
for(p = my_list_head.Flink; p != &my_list_head.Flink; p = p->Flink){
PMY_FILE_INFOR elem = CONTAINING_RECORD(p, //Address
MY_FILE_INFOR, //Type
list_entry); //Field
KdPrint(("node of MY_FILE_INFOR list, name: %wZ, length:%d\n",&elem->file_name,elem->file_length.QuadPart));
if(elem->file_length.QuadPart > 1000){
KdPrint(("file length > 1000,LowPart = %d, HighPart = %d\n",elem->file_length.LowPart,elem->file_length.HighPart));
}
}
return;
}
6 文件操作
/*
*《Windows驱动编程基础教程-谭文》- 文件操作
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
/*
*需要在C盘根目录下放一个study.txt文件,写入任意内容,当作拷贝的原文件
*/
#include<ntddk.h>
#include<ntdef.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
VOID StudyBakFileThread(VOID);
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
DriverObject->DriverUnload = StudyUnload;
StudyBakFileThread();
return STATUS_SUCCESS;
}
VOID
StudyBakFileThread()
{
UNICODE_STRING src_name = RTL_CONSTANT_STRING(L"\\DosDevices\\c:\\study.txt");
UNICODE_STRING dst_name = RTL_CONSTANT_STRING(L"\\DosDevices\\c:\\study.bak");
HANDLE src = NULL, dst = NULL; //the handles of the files to be copyed and copyed to
PVOID buffer = NULL;
OBJECT_ATTRIBUTES object_attributes_src,object_attributes_dst;
LARGE_INTEGER offset = {0};
IO_STATUS_BLOCK io_status = {0};
NTSTATUS status;
int length;
do{
InitializeObjectAttributes(
&object_attributes_src,
&src_name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = ZwCreateFile(
&src,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&object_attributes_src,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
InitializeObjectAttributes(
&object_attributes_dst,
&dst_name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = ZwCreateFile(
&dst,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&object_attributes_dst,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
buffer = ExAllocatePoolWithTag(PagedPool,4096,MEM_TAG);
if(NULL == buffer){
KdPrint(("FAIL ExAllocatePoolWithTag"));
return;
}
while(1){
length = 4*1024;
status = ZwReadFile(
src,NULL,NULL,NULL,
&io_status,
buffer,
length,
&offset,
NULL);
if(!NT_SUCCESS(status)){
if(STATUS_END_OF_FILE)
status = STATUS_SUCCESS;
break;
}
length = io_status.Information;
status = ZwWriteFile(
dst,NULL,NULL,NULL,
&io_status,
buffer,
length,
&offset,
NULL);
if(!NT_SUCCESS(status))
break;
offset.QuadPart += length;
}
}while(0);
if(NULL != src)
ZwClose(src);
if(NULL != dst)
ZwClose(dst);
if(NULL != buffer)
ExFreePool(buffer);
}
VOID
StudyUnload(PDRIVER_OBJECT DriverObject)
{
return;
}
7 注册表读写
/*
*《Windows驱动编程基础教程-谭文》- 注册表读写
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
VOID StudyRegistry(VOID);
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
DriverObject->DriverUnload = StudyUnload;
StudyRegistry();
return STATUS_SUCCESS;
}
VOID
StudyRegistry()
{
HANDLE my_key = NULL;
NTSTATUS status;
//read
UNICODE_STRING my_key_path = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
UNICODE_STRING my_key_name = RTL_CONSTANT_STRING(L"SystemRoot");
UNICODE_STRING my_key_value;
//write
UNICODE_STRING wr_name = RTL_CONSTANT_STRING(L"Test");
PCHAR wr_value = {L"Test Value"};
OBJECT_ATTRIBUTES my_obj_attr = {0};
KEY_VALUE_PARTIAL_INFORMATION key_infor; //tmp key_infor to test the length
PKEY_VALUE_PARTIAL_INFORMATION ac_key_infor; //actual key infor we use.buffer in dui
ULONG ac_length;
InitializeObjectAttributes(
&my_obj_attr,
&my_key_path,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwOpenKey(
&my_key,
KEY_READ,
&my_obj_attr);
if(!NT_SUCCESS(status)){
KdPrint(("ERROR - ZwOpenKey"));
return;
}
//get the real length of the key
status = ZwQueryValueKey(
my_key, //HANDLE KeyHandle,
&my_key_name,
KeyValuePartialInformation,
&key_infor,
sizeof(KEY_VALUE_PARTIAL_INFORMATION),
&ac_length);
if(!NT_SUCCESS(status) &&
STATUS_BUFFER_OVERFLOW != status &&
STATUS_BUFFER_TOO_SMALL != status){
KdPrint(("ERROR - ZwQueryValueKey"));
return;
}
//Allocate enough space
ac_key_infor = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool,ac_length,MEM_TAG);
if(ac_key_infor == NULL){
KdPrint(("ERROR - Allocate space for ac_key_infor"));
return;
}
status = ZwQueryValueKey(
my_key, //HANDLE KeyHandle,
&my_key_name,
KeyValuePartialInformation,
ac_key_infor,
ac_length,
&ac_length);
if(NT_SUCCESS(status)){
KdPrint(("SystemRoot is:%ws\n",ac_key_infor->Data));
}
status = ZwSetValueKey(
my_key, //IN HANDLE KeyHandle,
&wr_name, //IN PUNICODE_STRING ValueName
0, //IN ULONG TitleIndex OPTIONAL,
REG_SZ, //IN ULONG Type,
wr_value, //IN PVOID Data,
(wcslen(wr_value)+1)*sizeof(WCHAR)); //IN ULONG DataSize
if(!NT_SUCCESS(status)){
KdPrint(("ERROR! - ZwSetValueKey"));
return;
}
}
VOID
StudyUnload(PDRIVER_OBJECT DriverObject)
{
return;
}
8 时间与定时
/*
*《Windows驱动编程基础教程-谭文》- 时间与定时
*测试环境:WinDDK 7600.16385.0 chk x86 WXP
*小默 整理
*/
#include<ntddk.h>
#include<ntdef.h>
#include<ntstrsafe.h>
#define MEM_TAG "CG"
DRIVER_UNLOAD StudyUnload;
typedef struct MY_TIMER_
{
KDPC dpc;
KTIMER timer;
PKDEFERRED_ROUTINE func;
int private_context;
}MY_TIMER,*PMY_TIMER;
VOID StudyGetTickCount(VOID);
VOID StudyCurTimeStr();
VOID StudySetTimer();
VOID StudyDcpRoutine(
PRKDPC dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
PAGED_CODE();
DriverObject->DriverUnload = StudyUnload;
StudyGetTickCount();
StudyCurTimeStr();
StudySetTimer();
return STATUS_SUCCESS;
}
VOID
StudyGetTickCount()
{
LARGE_INTEGER tick_count;
ULONG time_inc = KeQueryTimeIncrement(); //the number of 100-nanosecond units between two interval clock interrupts
KeQueryTickCount(&tick_count); //count of the interval clock interrupts that have occurred since the system was booted
tick_count.QuadPart *= time_inc;
tick_count.QuadPart /= 10000;
KdPrint(("the system has been booted %d ms\n",tick_count.LowPart));
return;
}
VOID
StudyCurTimeStr()
{
LARGE_INTEGER snow,now;
TIME_FIELDS now_fields;
WCHAR time_str[32] = { 0 };
KeQuerySystemTime(&snow); //get the current system time of the GMT time zone
ExSystemTimeToLocalTime(&snow,&now); //adjust this value for the local time zone
RtlTimeToTimeFields(&now,&now_fields);
RtlStringCchPrintfW(
time_str,
32*2,
L"%4d-%2d-%2d %2d-%2d-%2d",
now_fields.Year,now_fields.Month,now_fields.Day,
now_fields.Hour,now_fields.Minute,now_fields.Second);
KdPrint(("The current time: %ws",&time_str));
}
VOID
StudySetTimer()
{
PMY_TIMER my_timer = (PMY_TIMER)ExAllocatePoolWithTag(PagedPool,sizeof(MY_TIMER),MEM_TAG);
LARGE_INTEGER due;
int msec = 1000;
due.QuadPart = -10000*msec;
my_timer->private_context = 5;
my_timer->func = StudyDcpRoutine;
KeInitializeDpc(
&my_timer->dpc, //PRKDPC Dpc
StudyDcpRoutine, //PKDEFERRED_ROUTINE DeferredRoutine,
my_timer); //PVOID DeferredContext
KeInitializeTimer(&my_timer->timer); //Init Timer
KdPrint(("before set timer"));
KeSetTimer(&my_timer->timer,due,&my_timer->dpc);
}
VOID
StudyDcpRoutine(
PRKDPC dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PMY_TIMER my_timer = (PMY_TIMER)DeferredContext;
KdPrint(("in dcp routine,context %d",my_timer->private_context));
}
VOID
StudyUnload(PDRIVER_OBJECT DriverObject)
{
return;
}