驅動代碼
#include<ntddk.h>
#define SYM_NAME L"\\??\\MaoYu"
// 驅動對象卸載的處理函數(回調)
void unLoad(PDRIVER_OBJECT pDriverObject)
{
// 如果驅動設備存在
if (pDriverObject->DeviceObject)
{
// 刪除符號鏈接
UNICODE_STRING symName;
RtlInitUnicodeString(&symName, SYM_NAME); // 初始化字符結構
IoDeleteSymbolicLink(&symName); // 刪除符號鏈接
// 刪除驅動設備
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("刪除設備成功"); // 打印調式信息
}
// 打印驅動卸載成功消息
DbgPrint("驅動卸載成功++++++++");
}
// IRP 請求 創建(回調) 1.驅動設備 2.rip對象
NTSTATUS myCreate(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用戶 創建動作");
// 將信息設置爲0
prip->IoStatus.Information = 0L;
// IRP的處理狀態
{
// 將請求設置爲成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO請求 1.IRP指針 2.系統定義的CCHAR常數
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 請求 清除 (回調) 1.驅動設備 2.rip對象
NTSTATUS myCleanUp(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用戶 清除動作");
// 將信息設置爲0
prip->IoStatus.Information = 0L;
// IRP的處理狀態
{
// 將請求設置爲成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO請求 1.IRP指針 2.系統定義的CCHAR常數
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 請求 關閉(回調) 1.驅動設備 2.rip對象
NTSTATUS myClose(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用戶 關閉動作");
// 將信息設置爲0
prip->IoStatus.Information = 0L;
// IRP的處理狀態
{
// 將請求設置爲成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO請求 1.IRP指針 2.系統定義的CCHAR常數
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 請求 讀取(回調) 1.驅動設備 2.rip對象
NTSTATUS myRead(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用戶 讀取動作");
// 返回一個指向呼叫者的I / O棧位置指定IRP,返回一個IO棧位置的結構體指針
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(prip);
// 拿到IRP要讀取的大小
ULONG size = pStack->Parameters.Read.Length;
// 處理IRP讀取動作
{
// 拿到IRP的緩衝區 SystemBuffer 指向系統空間緩衝區的指針 PVOID類型
PVOID buffer = prip->AssociatedIrp.SystemBuffer;
// 定義一個字符串
const char* content = "我是大貓魚";
// 計算字符串的長度
size_t count = strlen(content);
// 將數據寫入到 IRP 緩衝區
RtlCopyMemory(buffer, content, strlen(content));
// IRP的格式信息 賦值爲寫入的長度
prip->IoStatus.Information = count;
}
// IRP結果的處理狀態
{
// 將請求設置爲成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO請求 1.IRP指針 2.系統定義的CCHAR常數
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 請求 寫入(回調) 1.驅動設備 2.rip對象
NTSTATUS myWrite(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用戶 寫入動作");
// 返回一個指向呼叫者的I / O棧位置指定IRP,返回一個IO棧位置的結構體指針
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(prip);
// 拿到IRP要寫入的大小
ULONG size = pStack->Parameters.Write.Length;
// 拿到IRP的緩衝區 SystemBuffer 指向系統空間緩衝區的指針 PVOID類型
PVOID buffer = prip->AssociatedIrp.SystemBuffer;
// 處理IRP請求
{
// 將IRP緩衝區的內容拷貝到設備擴展字節緩衝區
RtlCopyMemory(pDveice->DeviceExtension, buffer, size);
// IRP的格式信息 賦值爲寫入的長度
prip->IoStatus.Information = size;
// 打印調式信息
DbgPrint("IRP:%s", (PCHAR)pDveice->DeviceExtension);
}
// IRP結果的處理狀態
{
// 將請求設置爲成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO請求 1.IRP指針 2.系統定義的CCHAR常數
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// 驅動入口函數 1.驅動對象指針 2.路徑的對象指針
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
// 設置驅動對象卸載回調以及打印調式信息
{
// 設置驅動對象的卸載函數
pDriverObject->DriverUnload = unLoad;
// 打印驅動加載成功消息
DbgPrint("驅動加載:%wS", pRegPath->Buffer);
}
// 驅動的名稱
UNICODE_STRING deviceName;
// 驅動設備對象指針
PDEVICE_OBJECT pDevice = NULL;
// 創建驅動設備
{
// 初始化Unicode字符串的計數器
RtlInitUnicodeString(&deviceName, L"\\Device\\MaoYu");
// 創建一個驅動程序使用的設備對象。
NTSTATUS status = IoCreateDevice(
pDriverObject, // 驅動對象地址
1024L, // 設備擴展的字節數大小
&deviceName, // 驅動設備的名稱
FILE_DEVICE_UNKNOWN, // 未知的設備
0L, // 有關設備的其它信息
TRUE, // 是否代表專業對象
&pDevice); // 驅動設備的指針
// 如果驅動設備創建失敗
if (status != STATUS_SUCCESS)
{
DbgPrint("創建驅動設備失敗"); // 打印錯誤信息
return status;
}
}
// 創建對外的符號鏈接
{
UNICODE_STRING symName; // 設備符號鏈接
// 初始化設備符號字符結構
RtlInitUnicodeString(&symName, SYM_NAME);
// 創建符號鏈接 1.符號鏈接的字符結構 2.驅動設備的名稱
NTSTATUS status = IoCreateSymbolicLink(&symName, &deviceName);
if (status != STATUS_SUCCESS)
{
DbgPrint("創建符號鏈接失敗"); // 打印錯誤信息
IoDeleteDevice(pDevice); // 刪除設備
return status;
}
}
// 設置 驅動對象的標誌類型 通過緩衝區進行 IO處理,注意要進行按位 或運算
pDevice->Flags |= DO_BUFFERED_IO;
// 處理IRP請求
{
// IRP創建動作
pDriverObject->MajorFunction[IRP_MJ_CREATE] = myCreate;
// IRP清除動作
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = myCleanUp;
// IRP關閉動作
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = myClose;
// IRP讀取動作
pDriverObject->MajorFunction[IRP_MJ_READ] = myRead;
// IRP寫入動作
pDriverObject->MajorFunction[IRP_MJ_WRITE] = myWrite;
}
return STATUS_SUCCESS;
}
c++代碼
#include<iostream>
#include<string>
#include<Windows.h>
int main(const int argc, const char** argv)
{
HANDLE hFile = NULL;
hFile = ::CreateFileW(
L"\\\\.\\MaoYu",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "設備打開失敗" << std::endl;
system("pause");
return 1;
}
else
{
std::cout << "設備打開成功" << std::endl;
}
system("pause");
// 讀取
{
PCHAR buffer[1024]{ 0 };
if (::ReadFile(hFile, buffer, sizeof(buffer), NULL, NULL))
{
printf("%s", buffer);
}
else
{
std::cout << "讀取錯誤" << std::endl;
system("pause");
::CloseHandle(hFile);
return 1;
}
system("pause");
}
// 寫入
{
std::string str = "hello word";
if (::WriteFile(hFile, str.c_str(), str.length(), NULL, NULL))
{
std::cout << "寫入成功" << std::endl;
}
else
{
std::cout << "寫入失敗" << std::endl;
}
}
system("pause");
::CloseHandle(hFile);
}
這簡單的實例,簡單的流程解釋
// 驅動端
1.創建一個驅動設備
2.創建這個設備的外部符號鏈接
3.設置這個設備的通信標誌(Flags)
4.設置IRP請求的回調函數
// 用戶端
1.打開一個設備
2.讀取設備的數據
3.寫入數據到設備
它們直接的交互,則是通過一個緩衝區。