当前位置:网站首页>Driver development - hellowdm driver
Driver development - hellowdm driver
2022-07-06 04:51:00 【ma_ de_ hao_ mei_ le】
Friend chain
hellowdm.h
// Make sure that the header file is compiled only once
// Because in real projects , A header file may be contained by another header file
// such as b.h It contains a.h
// And then in c.c Has the following code :
/*
#include<a.h>
#include<b.h>
*/
// thus ,a.h It was included twice
// and #pragma once Can guarantee a.h It is compiled only once
// So as to improve the compilation efficiency
#pragma once
// The following condition is compiled in C++ It is very common in projects
// It allows us to C++ Project use C Header file in
#ifdef __cplusplus
extern "C"
{
#endif
#include <wdm.h>
#ifdef __cplusplus
}
#endif
// Paging mark 、 Non paged marking and initialization of memory blocks
#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
// INIT The flag indicates that the function only needs to be loaded into memory when loading
// After the driver is successfully loaded , Functions can be unloaded from memory
#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]))
// Define body _DEVICE_EXTENSION , And name it
// Device extension structure
// This structure is widely used in drivers
// According to the needs of different procedures , It is used to supplement and define the relevant information of the equipment
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT fdo;
PDEVICE_OBJECT NextStackDevice;
UNICODE_STRING ustrDeviceName; // Equipment name
UNICODE_STRING ustrSymLinkName; // Symbolic link name
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
// Function declaration
// This IN The keyword may be used to indicate that the parameter is an incoming parameter
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT pDriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
IN PIRP Irp);
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
IN PIRP Irp);
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);
HelloWDM.cp
#include "HelloWDM.h"
/*
Initialize the driver , Locate and apply for hardware resources , Create kernel objects
parameter list
pDriverObject: from IO The driver object passed in the manager
pRegistryPath: The path of the driver in the registry
Return value :
Return to initialization driver state
*/
// Use extern "C" Decorate the function , In this way, it will be compiled into [email protected]
// Without this modifier , The compiler will follow C++ The symbolic name of , Link time will report an error
// Indicates that the function is loaded into INIT In the memory area
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath)
{
// There are no programs running in the kernel console Of , So you can only use KdPrint Macro to output debugging information
// This macro only works in debug versions (Free)
// Do nothing in the release (Checked)
KdPrint(("Enter DriverEntry\n"));
// Register other driver call function entries
// Send the address of our own defined function to the operating system
// The operating system will call these functions when appropriate
// AddDevice Callback functions only appear in WDM In driver , stay NT There is no callback function in the driver of type
// This function is used to create a device object and generate it by PNP( Plug and play ) Manager calls
pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
// Yes PNP Of IRP Handle ,IRP It will be introduced later , This is also NT The type and WDM One of the major differences of type drive
pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
// This is just a demonstration , So it all points to a simple function HelloWDMDispatchRoutine
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_READ] =
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
// Register uninstall function
pDriverObject->DriverUnload = HelloWDMUnload;
KdPrint(("Leave DriverEntry\n"));
return STATUS_SUCCESS;
}
// Definition IRP Default handler
#pragma PAGEDCODE
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
// Make sure that the routine is in APC_LEVEL under
PAGED_CODE();
KdPrint(("Enter DefaultPnPHandler\n"));
// Skip the current stack
IoSkipCurrentIrpStackLocation(Irp);
KdPrint(("Leave DefaultPnpHandler\n"));
// Use the driver device object of the lower stack to handle this IRP
return IoCallDriver(pdx->NextStackDevice, Irp);
}
#pragma PAGEDCODE
// This function is similar to NT Unloading routine in the driver , stay WDM Type drive , The unloading process requires little processing
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
PAGED_CODE();
KdPrint(("Enter HandleRemoveDevice\n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
// Call the default IRP Processing function
NTSTATUS status = DefaultPnpHandler(pdx, Irp);
// Remove symbolic links
IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
// call IoDetachDevice Function will fdo Detach from the device stack
if(pdx->NextStackDevice)
IoDetachDevice(pdx->NextStackDevice);
// Delete fdo
IoDeleteDevice(pdx->fdo);
KdPrint(("Leave HandleRemoveDevice\n"));
return status;
}
// stay WDM Type driver , Creating devices is no longer done by DriverEntry To undertake , But through AddDevice Callback function
#pragma PAGEDCODE
NTSTATUS HelloWDMAddDevice(
/* pDriverObject By PNP The driver object passed in by the manager , and DriverEntry The parameters in the function are consistent */
IN PDRIVER_OBJECT pDriverObject,
/* PhysicalDeviceObject By PNP The underlying driver device object passed in by the manager , stay NT There is no such concept in the type drive */
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
// This is a macro , If the interrupt request level of this routine exceeds APC_LEVEL when , Will produce an assertion , This assertion will cause the program to terminate and report an error address
// Interrupt request level will be introduced later
PAGED_CODE();
KdPrint(("ENter HelloWDMAddDevice\n"));
NTSTATUS status;
PDEVICE_OBJECT fdo;
// Equipment name
// structure Unicode The string is used to store the name of this device object
UNICODE_STRING devName;
RtlInitUnicodeString(&devName, L"\\Device\\MyWDMDevice");
// Create device
status = IoCreateDevice(pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fdo);
if(!NT_SUCCESS(status))
return status;
// Fill in the extended structure of the equipment
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->fdo = fdo;
// take fdo( Functional device object ) Hook on device stack , And record its return value in the device extension structure
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
pdx->ustrDeviceName = devName;
// Create symbolic links
// The device name is only visible in kernel mode , User programs are invisible
// Therefore, a symbolic connection needs to be exposed , The symbolic link points to the real device name
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK");
pdx->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName);
// If it is created successfully, it will return , Otherwise, call IoDeleteDevice Delete device
if(!NT_SUCCESS(status))
{
// I don't know why I tried to create it again , The device was not deleted , It's a deleted symbolic link
// If it fails , It should not be that symbolic links are not created at all ? You can also delete ?
// I feel there is something wrong with the code , I annotated him out
/*
IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
status = IoCreateSymbolicLink(&symLinkName, &devName);
if(!NT_SUCCESS(status))
{
return status;
}
*/
IoDeleteDevice(fdo);
return status;
}
// Set the device to BUFFER_IO equipment , And indicate that the driver initialization is complete
fdo->Flags = fdo->Flags | DO_POWER_PAGABLE;
fdo->Flags = fdo->Flags & ~DO_DEVICE_INITIALIZING;
KdPrint(("Leave HelloWDMAddDevice\n"));
return STATUS_SUCCESS;
}
// Definition HelloWDMPnp function , Yes, plug and play IRP To deal with
#pragma PAGEDCODE
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PAGED_CODE();
KdPrint(("Enter HelloWDMPnp\n"));
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
// Get the present IRP The stack , Device stack is a very complex concept , I'll talk about it later
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
// Initialize the function table
// Plug and play the corresponding category IRP Call to do different processing
static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
{
DefaultPnpHandler, // IRP_MN_START_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE
HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS
DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
DefaultPnpHandler, //
DefaultPnpHandler, // IRP_MN_READ_CONFIG
DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
DefaultPnpHandler, // IRP_MN_EJECT
DefaultPnpHandler, // IRP_MN_SET_LOCK
DefaultPnpHandler, // IRP_MN_QUERY_ID
DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL
};
ULONG fcn = stack->MinorFunction;
if(fcn >= arraysize(fcntab))
{
// For the unknown IRP Category , Use DefaultPnpHandler Function to handle
status = DefaultPnpHandler(pdx, Irp);
return status;
}
#if DBG
static char* fcnname[] =
{
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL"
};
KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
#endif
status = (*fcntab[fcn])(pdx, Irp);
KdPrint(("Leave HelloWDMPnp\n"));
return status;
}
#pragma PAGEDCODE
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
// And before HelloDDK The code is almost consistent :https://blog.csdn.net/ma_de_hao_mei_le/article/details/125596301
PAGED_CODE();
KdPrint(("Enter HelloWDMDispatchRoutine\n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint(("Leave HelloWDMDispatchRoutine\n"));
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
// Responsible for driver uninstallation
// Because the unloading task of the driver is put in IRP_MN_REMOVE_DEVICE In the processing function
// So there is no need HelloWDMUnload To do , Just print two lines of debugging information
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
{
PAGED_CODE();
KdPrint(("Enter HelloWDMUnload\n"));
KdPrint(("Leave HelloWDMUnload\n"));
}
source
TARGETNAME=HelloWDM
TARGETTYPE=DRIVER
DRIVERTYPE=WDM
TARGETPATH=OBJ
INCLUDES=$(BASEDIR)\inc;\
$(BASEDIR)\inc\ddk;\
SOURCES=HelloWDM.cpp\
边栏推荐
- Distributed transaction solution
- Summary of redis AOF and RDB knowledge points
- SQL注入漏洞(MSSQL注入)
- Ue5 small knowledge points to enable the setting of lumen
- 2021robocom robot developer competition (Preliminary)
- Request (request object) and response (response object)
- Redis has four methods for checking big keys, which are necessary for optimization
- SQL injection vulnerability (MSSQL injection)
- acwing周赛58
- Scala function advanced
猜你喜欢
Distributed transaction solution
RTP gb28181 document testing tool
11. Intranet penetration and automatic refresh
A blog to achieve embedded entry
Redis - redis in action - redis actual combat - actual combat Chapter 1 - SMS login function based on redis - redis + token shared session application - with code
ue5 小知识点 开启lumen的设置
Why does MySQL need two-phase commit
麥斯克電子IPO被終止:曾擬募資8億 河南資產是股東
Visio draws Tai Chi
Postman assertion
随机推荐
2021 robocom world robot developer competition - undergraduate group (semi-finals)
A blog to achieve embedded entry
Complete list of common functions of turtle module
The video in win10 computer system does not display thumbnails
How does vs change the project type?
[NOIP2009 普及组] 分数线划定
也算是學習中的小總結
Hometown 20 years later (primary school exercises)
Programmers' position in the Internet industry | daily anecdotes
最高法院,离婚案件判决标准
内核判断i2c地址上是否挂载外设
word封面下划线
[Yu Yue education] reference materials of complex variable function and integral transformation of Northwestern Polytechnic University
树莓派3.5寸屏幕白屏显示连接
acwing周赛58
Canal synchronizes MySQL data changes to Kafka (CentOS deployment)
Visio draw fan
Redis 排查大 key 的4种方法,优化必备
Biscuits (examination version)
Distributed transaction solution