windows驱动编程(一) 先写个NTDDK例子

参考张帆的windows驱动开发技术详解,自学中。。。
#pragma once

#ifndef __HELLODDK__HH
#define __HELLODDK__HH

//包含ntddk.h文件,使用c标准的方式编译
#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
#ifdef __cplusplus
};
#endif

//定义分页标记,非分页标记和初始化内存块,
//在windows驱动程序的开发中,所有程序的函数和变量都有指明被加载到分页内存还是非分页内存
//DriverEntry函数需要放在INIT标志的内存中
//关于区别后续解释
#define  PAGEDCODE	 code_seg("PAGE")
#define  LOCKEDCODE	 code_seg()
#define  INITCODE	 code_seg("INIT")

#define PAGEDDATA	data_seg("PAGE")
#define LOCKEDDATA	data_seg()
#define INITDATA	data_seg("INIT")


#define arraySize(p)	(sizeof(p)/sizeof((p)[0])) //得到数组的元素个数

//设备扩展结构体,根据个人需要可以添加所需信息
typedef struct _DEVICE_EXTENSION 
{
	PDEVICE_OBJECT pDevice; //设备结构体指针
	UNICODE_STRING usDeviceName;//设备名称
	UNICODE_STRING usSymLinkName;//符号连接名

}DEVICE_EXTENSION,*pDEVICE_EXTENSION;

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject); //创建设备
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject);//卸载设备
NTSTATUS HelloDDKDispatchRoutine(IN PDRIVER_OBJECT pDriverObject,IN PIRP pIrp);//通用的设备例程函数


#endif



#include "MyDDKHello.h"

/*
DriverEntry:驱动程序的入口函数
功能:初始化驱动程序,申请硬件资源,创建内核对象
参数:
IN pDriverObject 从I/O管理器中传进来的驱动对象
IN pRegisterPath 驱动程序在注册表中的路径
返回:返回初始化驱动的状态
*/
//#include <wdm.h>
#pragma  INITCODE
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegisterPath)
{
	NTSTATUS status;

	DbgPrint("Into DriverEntry..."); //相当于TRACRE()

	//向I/O管理器注册驱动回调函数
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = 
		pDriverObject->MajorFunction[IRP_MJ_CLOSE] = 
		pDriverObject->MajorFunction[IRP_MJ_WRITE] = 
		pDriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)HelloDDKDispatchRoutine;

	pDriverObject->DriverUnload = HelloDDKUnload;

	status = CreateDevice(pDriverObject);

	DbgPrint("DriverEntry End...");

	return status;

}


/*
CreateDevice:初始化设备对象
参数:pDriverObject 从I/O管理器传进来的驱动对象
返回:返回创建设备的初始化状态
*/

#pragma INITCODE
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	PDEVICE_OBJECT pDeviceObject;

	//设备的扩展结构体,其他的驱动程序的函数中,可以很方便的得到此结构体,进而得到设备的自定义信息
	pDEVICE_EXTENSION pDevExt; 

	//创建设备名
	UNICODE_STRING usDevName;
	RtlInitUnicodeString(&usDevName,L"\\Device\\MyDDKDevice"); //初始化UNICODE_STRING类型的变量,使用后不需要释放

	//创建设备
	status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&usDevName,
		FILE_DEVICE_UNKNOWN,//此种设备为独占设备,设备只能被一个应用程序所使用 
		0, //
		TRUE,//
		&pDeviceObject);

	if (!NT_SUCCESS(status))
	{
		return status;
	}

	pDeviceObject->Flags |= DO_BUFFERED_IO; //设备对内存的操作分类:DO_BUFFERED_IO DO_DIRECT_IO ,详解后说明
	pDevExt = (pDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
	pDevExt->pDevice = pDeviceObject;
	pDevExt->usDeviceName = usDevName;

	//创建符号连接
	UNICODE_STRING usSymLinkName;
	RtlInitUnicodeString(&usSymLinkName,L"\\??\\MySymbLinkNameHelloDDK");
	pDevExt->usSymLinkName = usSymLinkName;

	//对于应用程序,设备名称是不可见的,只能使用符号连接名称,该连接指向真正的设备名称
	status = IoCreateSymbolicLink(&usSymLinkName,&usDevName);

	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDeviceObject); //删除设备对象
		return status;
	}

	return STATUS_SUCCESS;

}

/*
HelloDDKUnload:负责驱动程序的卸载操作
参数: pDriverObject :驱动程序对象
*/
/*
此历程遍历系统中所有的此类设备对象。第一个设备对象的地址存在于驱动对象的DeviceObject域中,
每个设备对象的NextDevice域记录着下一个设备对象的地址,这样就形成了一个链表。
卸载驱动函数的主要目的就是遍历此链表,获得设备名称和符号链接名称,并执行删除操作。
*/
#pragma  PAGEDCODE
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	PDEVICE_OBJECT pDevNext;
	DbgPrint("into HelloDDKUnload");

	pDevNext = pDriverObject->DeviceObject;
	while (pDevNext != NULL)
	{
		pDEVICE_EXTENSION pDevExt = (pDEVICE_EXTENSION)pDevNext->DeviceExtension;

		//删除符号链接
		UNICODE_STRING usLinkName = pDevExt->usSymLinkName;
		IoDeleteSymbolicLink(&usLinkName);

		pDevNext = pDevNext->NextDevice;
		IoDeleteDevice(pDevNext); //删除设备
	}

}

/*
HelloDDKDispatchRoutine:默认派遣函数
参数:
pDriverObject:功能设备对象
pIrp:从I/O请求包
返回值:返回处理的状态
*/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDRIVER_OBJECT pDriverObject,IN PIRP pIrp)
{

	DbgPrint("in to HelloDDKDispatchRoutine");
	NTSTATUS status = STATUS_SUCCESS;

	//完成IRP
	pIrp->IoStatus .Status= status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp,
		IO_NO_INCREMENT//后续详解
		);

	DbgPrint("end HelloDDKDispatchRoutine");

	return  status;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值