簡介
??從魯大師的溫度監(jiān)控談起,現(xiàn)代的CPU、GPU等芯片一般都具有溫度監(jiān)控的功能,比如我們可能會遇到的電腦散熱不好導(dǎo)致系統(tǒng)直接關(guān)機(jī)黑屏,就是cpu檢測到當(dāng)前溫度高于額定溫度執(zhí)行的操作。
??魯大師的溫度監(jiān)控模塊就相當(dāng)于把這些信息從底層硬件讀取,然后通過上層UI顯示給用戶。其核心就是與硬件的通信驅(qū)動?,F(xiàn)在win10的驅(qū)動都可以通過系統(tǒng)更新直接完成,不再需要安裝流氓軟件“驅(qū)動精靈”、“驅(qū)動人生”等。我一般只用到溫度檢測模塊,其他功能于我都是雞肋,為了一個很小的功能,我需要安裝一個龐大的魯大師程序,甚是不劃算。故自己動手實(shí)現(xiàn)。本文的主題就是如何實(shí)現(xiàn)魯大師的溫度檢測模塊。
??封閉必將導(dǎo)致落后,開放才能共同進(jìn)步。WinRing0.sys作為一款windows平臺下與設(shè)備通信的驅(qū)動被廣泛使用。卻由開源成了閉源,由支持讀寫成了僅支持讀。本文花費(fèi)數(shù)個工作日將08年之前開源的文件進(jìn)行學(xué)習(xí)整理。便于后期大家的學(xué)習(xí)和升級優(yōu)化。
windows驅(qū)動預(yù)備知識
1.虛擬設(shè)備驅(qū)動程序
.vxd程序:
虛擬設(shè)備驅(qū)動程序,主要是為了給dos程序提供一個虛擬硬件
dos程序:
早于windows的程序,window 3.x時代為了發(fā)展就需要兼容這些程序。類似當(dāng)前鴻蒙兼容安卓,都是為了錢,不磕磣。
.vxd程序:
可以把.vxd程序理解為運(yùn)行在第0級別的dll。
ring0:
最高等級權(quán)限,可以為所欲為,直接操作硬件。
ring3:
用戶等級權(quán)限,可以調(diào)用user32.dll、NTDLL.dll等庫間接控制硬件。
WinRing0.vxd:
其目的并非要虛擬硬件,只是需要第0級別的權(quán)限。
總結(jié)一:.vxd程序最新也得win9的系統(tǒng)才能用到,以上當(dāng)個科普,了解下就行。對應(yīng)WingRing0驅(qū)動的學(xué)習(xí)聚焦到.sys文件。
2.設(shè)備驅(qū)動文件
.sys文件
:設(shè)備驅(qū)動文件,常說的聲卡、顯卡、鍵盤驅(qū)動等,都需要開發(fā)這種文件。
.inf文件
:驅(qū)動安裝的配置文件,主要是寫注冊表,注冊接口。必有參數(shù)是ClassGUID。
總結(jié)二:.sys文件也當(dāng)做權(quán)限等級為0級的.dll文件就行了。.dll文件的使用不熟悉的可以網(wǎng)上了解下。
3.sys驅(qū)動使用
.簽名
:內(nèi)核級別的驅(qū)動都需要微軟公司認(rèn)證過的秘鑰進(jìn)行簽名才能直接安裝到windows系統(tǒng)中。簽名的秘鑰文件后綴是.cer。注冊
:注冊僅僅是完成在注冊表里寫一個項(xiàng)。下圖中的小工具是專門用于內(nèi)核驅(qū)動安裝運(yùn)行的。鏈接: 下載地址
啟動
:對應(yīng)缺微軟簽名或微軟認(rèn)證過的秘鑰進(jìn)行簽名的內(nèi)核級驅(qū)動是無法直接啟動起來的。這是由于系統(tǒng)對于涉及內(nèi)核層級的驅(qū)動有簽名校驗(yàn)導(dǎo)致,簡單說就是沒有健康碼綠碼的不能在小區(qū)活動。
禁用強(qiáng)制簽名校驗(yàn)
:通過修改bcdedit來取消掉這個限制。有點(diǎn)類似安卓手機(jī)安裝APP的時候經(jīng)常需要“允許安裝未知來源的程序”。逐條執(zhí)行以下命令即可(管理員權(quán)限):
"Win7系統(tǒng)"
bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS
bcdedit /set TESTSIGNING ON
bcdedit /set nointegritychecks yes
如果有失敗項(xiàng),一般需要在BIOS里面關(guān)閉安全啟動
啟動按DEL鍵 進(jìn)入BIOS 然后把 Secure Boot Policy 選項(xiàng)設(shè)置為關(guān)閉
重啟電腦
"Win10系統(tǒng)"
bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS
bcdedit /set TESTSIGNING ON
bcdedit /set nointegritychecks yes
如果有失敗,一般需要在BIOS里面關(guān)閉安全啟動
啟動按DEL鍵 進(jìn)入BIOS 然后把 Secure Boot Policy 選項(xiàng)設(shè)置為關(guān)閉
重啟電腦
代碼分析
??通過以上的知識大致了解了windows驅(qū)動程序是啥,怎么用。接下來就進(jìn)入較難的實(shí)戰(zhàn)部分,寫代碼調(diào)用驅(qū)動獲取有效信息。.sys驅(qū)動是用c語言寫的,具體代碼如下三部分。
1、驅(qū)動入口函數(shù)
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
NTSTATUS status;
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;
PDEVICE_OBJECT deviceObject = NULL;
RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
status = IoCreateDevice(
DriverObject, // Our Driver Object
0, // We don't use a device extension
&ntDeviceName, // Device name
OLS_TYPE, // Device type 自定義的值
FILE_DEVICE_SECURE_OPEN, // Device characteristics
FALSE, // Not an exclusive device 非排他性設(shè)備
&deviceObject ); // Returned ptr to Device Object
if(!NT_SUCCESS(status))
{
refCount = (ULONG)-1;
return status;
}
else
{
refCount = 0;
}
// Initialize the driver object with this driver's entry points.
// 構(gòu)造DriverObject這個結(jié)構(gòu)體變量
DriverObject->MajorFunction[IRP_MJ_CREATE] = OlsDispatch;// 1.注冊函數(shù),就是把函數(shù)指針告訴操作系統(tǒng)。當(dāng)操作系統(tǒng)發(fā)送 IRP_MJ_CREATE 請求時,會調(diào)用這個函數(shù)
DriverObject->MajorFunction[IRP_MJ_CLOSE] = OlsDispatch;// 2.
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OlsDispatch;// 3.
DriverObject->DriverUnload = Unload;//驅(qū)動卸載函數(shù)
// Initialize a Unicode String containing the Win32 name for our device.
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
// Create a symbolic link between our device name and the Win32 name
status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);
if (!NT_SUCCESS(status))
{
// Delete everything that this routine has allocated.
IoDeleteDevice( deviceObject );
}
return status;
}
2、調(diào)度函數(shù)
??實(shí)際讀取CPU信息的實(shí)現(xiàn)代碼在此處,主要涉及兩個參數(shù),其一是:DEVICE_OBJECT ,其二是:I/O Request Packet (IRP) 。OlsDispatch()這個函數(shù)根據(jù)傳進(jìn)來的請求信息調(diào)用具體的執(zhí)行函數(shù)。
/*++
Routine Description:
This routine is the dispatch handler for the driver. It is responsible
for processing the IRPs.
Arguments:
pDO - Pointer to device object.
pIrp - Pointer to the current IRP.
Return Value:
STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
indicating the reason for failure.
--*/
NTSTATUS OlsDispatch( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
{
PIO_STACK_LOCATION pIrpStack;
NTSTATUS status;
int index;
// Initialize the irp info field.
// This is used to return the number of bytes transfered.
pIrp->IoStatus.Information = 0;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// Set default return status
status = STATUS_NOT_IMPLEMENTED;
// Dispatch based on major fcn code.
switch(pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
if(refCount != (ULONG)-1){refCount++;}
status = STATUS_SUCCESS;
break;
case IRP_MJ_CLOSE:
if(refCount != (ULONG)-1){refCount--;}
status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
// Dispatch on IOCTL
switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_OLS_GET_DRIVER_VERSION:
*(PULONG)pIrp->AssociatedIrp.SystemBuffer = OLS_DRIVER_VERSION;
pIrp->IoStatus.Information = 4;
status = STATUS_SUCCESS;
break;
case IOCTL_OLS_GET_REFCOUNT:
*(PULONG)pIrp->AssociatedIrp.SystemBuffer = refCount;
pIrp->IoStatus.Information = sizeof(refCount);
status = STATUS_SUCCESS;
break;
case IOCTL_OLS_READ_MSR:
status = ReadMsr(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_WRITE_MSR:
status = WriteMsr(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_READ_PMC:
status = ReadPmc(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_HALT:
__halt();
status = STATUS_SUCCESS;
break;
case IOCTL_OLS_READ_IO_PORT:
case IOCTL_OLS_READ_IO_PORT_BYTE:
case IOCTL_OLS_READ_IO_PORT_WORD:
case IOCTL_OLS_READ_IO_PORT_DWORD:
status = ReadIoPort(
pIrpStack->Parameters.DeviceIoControl.IoControlCode,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_WRITE_IO_PORT:
case IOCTL_OLS_WRITE_IO_PORT_BYTE:
case IOCTL_OLS_WRITE_IO_PORT_WORD:
case IOCTL_OLS_WRITE_IO_PORT_DWORD:
status = WriteIoPort(
pIrpStack->Parameters.DeviceIoControl.IoControlCode,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_READ_PCI_CONFIG:
status = ReadPciConfig(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_WRITE_PCI_CONFIG:
status = WritePciConfig(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_READ_MEMORY:
status = ReadMemory(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
case IOCTL_OLS_WRITE_MEMORY:
status = WriteMemory(
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
(ULONG*)&pIrp->IoStatus.Information
);
break;
}
break;
}
// We're done with I/O request. Record the status of the I/O action.
pIrp->IoStatus.Status = status;
// Don't boost priority when returning since this took little time.
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
??下面的代碼是具體每個case的實(shí)現(xiàn)部分,直接在注釋里面做介紹:文章來源:http://www.zghlxwxcb.cn/news/detail-627952.html
//-----------------------------------------------------------------------------
//
// CPU
//
//-----------------------------------------------------------------------------
NTSTATUS
ReadMsr( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
__try
{
//MSR是CPU的一組64位寄存器,可以分別通過RDMSR和WRMSR 兩條指令進(jìn)行讀和寫的操作。
//__readmsr就是生成指令并執(zhí)行。此函數(shù)僅在內(nèi)核模式下可用,且對應(yīng)程序僅可用作內(nèi)部函數(shù),
//這也就是為啥需要Ring0權(quán)限的原因。
ULONGLONG data = __readmsr(*(ULONG*)lpInBuffer);
memcpy((PULONG)lpOutBuffer, &data, 8);
*lpBytesReturned = 8;
return STATUS_SUCCESS;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
*lpBytesReturned = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
WriteMsr( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
__try
{
//與上面的__readmsr類似
OLS_WRITE_MSR_INPUT* param;
param = (OLS_WRITE_MSR_INPUT*)lpInBuffer;
__writemsr(param->Register, param->Value.QuadPart);
*lpBytesReturned = 0;
return STATUS_SUCCESS;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
*lpBytesReturned = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
ReadPmc( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
__try
{ //pmc 性能計數(shù)器
ULONGLONG data = __readpmc(*(ULONG*)lpInBuffer);
memcpy((PULONG)lpOutBuffer, &data, 8);
*lpBytesReturned = 8;
return STATUS_SUCCESS;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
*lpBytesReturned = 0;
return STATUS_UNSUCCESSFUL;
}
}
//-----------------------------------------------------------------------------
//
// IO Port IO口
//
//-----------------------------------------------------------------------------
NTSTATUS
ReadIoPort( ULONG ioControlCode,
void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
ULONG nPort = *(ULONG*)lpInBuffer;
switch(ioControlCode)
{
case IOCTL_OLS_READ_IO_PORT_BYTE://從指定的端口地址讀取單個字節(jié)
*(PUCHAR)lpOutBuffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort);
break;
case IOCTL_OLS_READ_IO_PORT_WORD://從指定的端口地址讀取單個字
*(PUSHORT)lpOutBuffer = READ_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort);
break;
case IOCTL_OLS_READ_IO_PORT_DWORD://從指定的端口地址讀取雙字節(jié)
*(PULONG)lpOutBuffer = READ_PORT_ULONG((PULONG)(ULONG_PTR)nPort);
break;
default:
*lpBytesReturned = 0;
return STATUS_INVALID_PARAMETER;
break;
}
*lpBytesReturned = nInBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
WriteIoPort(ULONG ioControlCode,
void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
ULONG nPort;
OLS_WRITE_IO_PORT_INPUT* param;
param = (OLS_WRITE_IO_PORT_INPUT*)lpInBuffer;
nPort = param->PortNumber;
switch(ioControlCode)
{
case IOCTL_OLS_WRITE_IO_PORT_BYTE:
WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort, param->CharData);
break;
case IOCTL_OLS_WRITE_IO_PORT_WORD:
WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort, param->ShortData);
break;
case IOCTL_OLS_WRITE_IO_PORT_DWORD:
WRITE_PORT_ULONG((PULONG)(ULONG_PTR)nPort, param->LongData);
break;
default:
return STATUS_INVALID_PARAMETER;
break;
}
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
//
// PCI
//
//-----------------------------------------------------------------------------
NTSTATUS
ReadPciConfig( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
OLS_READ_PCI_CONFIG_INPUT *param;
NTSTATUS status;
if(nInBufferSize != sizeof(OLS_READ_PCI_CONFIG_INPUT))
{
return STATUS_INVALID_PARAMETER;
}
param = (OLS_READ_PCI_CONFIG_INPUT *)lpInBuffer;
status = pciConfigRead(param->PciAddress, param->PciOffset,
lpOutBuffer, nOutBufferSize);//最終調(diào)用的是HalGetBusDataByOffset,這是硬件抽象層函數(shù),獲取總線數(shù)據(jù)
if(status == STATUS_SUCCESS)
{
*lpBytesReturned = nOutBufferSize;
}
else
{
*lpBytesReturned = 0;
}
return status;
}
NTSTATUS
WritePciConfig( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
OLS_WRITE_PCI_CONFIG_INPUT *param;
ULONG writeSize;
NTSTATUS status;
if(nInBufferSize < offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data))
{
return STATUS_INVALID_PARAMETER;
}
param = (OLS_WRITE_PCI_CONFIG_INPUT *)lpInBuffer;
writeSize = nInBufferSize - offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data);
*lpBytesReturned = 0;
return pciConfigWrite(param->PciAddress, param->PciOffset,
¶m->Data, writeSize);
}
//-----------------------------------------------------------------------------
//
// Support Function
//
//-----------------------------------------------------------------------------
NTSTATUS pciConfigRead(ULONG pciAddress, ULONG offset, void *data, int length)
{
PCI_SLOT_NUMBER slot;
int error;
ULONG busNumber;
busNumber = PciGetBus(pciAddress);
slot.u.AsULONG = 0;
slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
error = HalGetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
data, offset, length);
if(error == 0)
{
return OLS_ERROR_PCI_BUS_NOT_EXIST;
}
else if(length != 2 && error == 2)
{
return OLS_ERROR_PCI_NO_DEVICE;
}
else if(length != error)
{
return OLS_ERROR_PCI_READ_CONFIG;
}
return STATUS_SUCCESS;
}
NTSTATUS pciConfigWrite(ULONG pciAddress, ULONG offset, void *data, int length)
{
PCI_SLOT_NUMBER slot;
int error;
ULONG busNumber;
busNumber = PciGetBus(pciAddress);
slot.u.AsULONG = 0;
slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
error = HalSetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
data, offset, length);
if(error != length)
{
return OLS_ERROR_PCI_WRITE_CONFIG;
}
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
//
// Physical Memory
//
//-----------------------------------------------------------------------------
NTSTATUS
ReadMemory( void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
OLS_READ_MEMORY_INPUT *param;
ULONG size;
PHYSICAL_ADDRESS address;
PVOID maped;
BOOLEAN error;
if(nInBufferSize != sizeof(OLS_READ_MEMORY_INPUT))
{
return STATUS_INVALID_PARAMETER;
}
param = (OLS_READ_MEMORY_INPUT *)lpInBuffer;
size = param->UnitSize * param->Count;
if(nOutBufferSize < size)
{
return STATUS_INVALID_PARAMETER;
}
address.QuadPart = param->Address.QuadPart;
#ifndef _PHYSICAL_MEMORY_SUPPORT
if(0x000C0000 > address.QuadPart
|| (address.QuadPart + size - 1) > 0x000FFFFF)
{
return STATUS_INVALID_PARAMETER;
}
#endif
maped = MmMapIoSpace(address, size, FALSE);//把物理地址 轉(zhuǎn)為虛擬地址,比如我們要讀取物理地址為100的一個字節(jié)數(shù)據(jù),
//其通過系統(tǒng)被映射到虛擬內(nèi)存的地址是200,那我們就通過讀虛擬內(nèi)存的200位置來實(shí)現(xiàn)
error = FALSE;
switch(param->UnitSize){
case 1:
READ_REGISTER_BUFFER_UCHAR(maped, lpOutBuffer, param->Count);//從虛擬地址里間接讀物理地址的信息
break;
case 2:
READ_REGISTER_BUFFER_USHORT(maped, lpOutBuffer, param->Count);
break;
case 4:
READ_REGISTER_BUFFER_ULONG(maped, lpOutBuffer, param->Count);
break;
default:
error = TRUE;
break;
}
MmUnmapIoSpace(maped, size);
if(error)
{
return STATUS_INVALID_PARAMETER;
}
*lpBytesReturned = nOutBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
WriteMemory(void *lpInBuffer,
ULONG nInBufferSize,
void *lpOutBuffer,
ULONG nOutBufferSize,
ULONG *lpBytesReturned)
{
#ifdef _PHYSICAL_MEMORY_SUPPORT
OLS_WRITE_MEMORY_INPUT *param;
ULONG size;
PHYSICAL_ADDRESS address;
PVOID maped;
BOOLEAN error;
if(nInBufferSize < offsetof(OLS_WRITE_MEMORY_INPUT, Data))
{
return STATUS_INVALID_PARAMETER;
}
param = (OLS_WRITE_MEMORY_INPUT *)lpInBuffer;
size = param->UnitSize * param->Count;
if (nInBufferSize < size + offsetof(OLS_WRITE_MEMORY_INPUT, Data))
{
return STATUS_INVALID_PARAMETER;
}
address.QuadPart = param->Address.QuadPart;
maped = MmMapIoSpace(address, size, FALSE);
error = FALSE;
switch(param->UnitSize){
case 1:
WRITE_REGISTER_BUFFER_UCHAR(maped,
(UCHAR*)¶m->Data, param->Count);
break;
case 2:
WRITE_REGISTER_BUFFER_USHORT(maped,
(USHORT*)¶m->Data, param->Count);
break;
case 4:
WRITE_REGISTER_BUFFER_ULONG(maped,
(ULONG*)¶m->Data, param->Count);
break;
default:
error = TRUE;
break;
}
MmUnmapIoSpace(maped, size);
if(error)
{
return STATUS_INVALID_PARAMETER;
}
*lpBytesReturned = 0;
return STATUS_SUCCESS;
#else
*lpBytesReturned = 0;
return STATUS_INVALID_PARAMETER;
#endif
}
3、驅(qū)動卸載函數(shù)
??實(shí)際的卸載工作被IRP_MN_REMOVE_DEVICE
對應(yīng)的派發(fā)函數(shù)處理了,不需要自己實(shí)現(xiàn)。這里的DriverUnload
主要處理在DriverEntry
中申請的內(nèi)存,也就是“new”出的“win32NameString”。文章來源地址http://www.zghlxwxcb.cn/news/detail-627952.html
/*++
Routine Description:
This routine is called by the I/O system to unload the driver.
Any resources previously allocated must be freed.
Arguments:
DriverObject - a pointer to the object that represents our driver.
Return Value:
None
--*/
VOID Unload( PDRIVER_OBJECT DriverObject )
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING win32NameString;
PAGED_CODE();
// Create counted string version of our Win32 device name.
RtlInitUnicodeString(&win32NameString, DOS_DEVICE_NAME);
// Delete the link from our device name to a name in the Win32 namespace.
IoDeleteSymbolicLink(&win32NameString);
if(deviceObject != NULL)
{
IoDeleteDevice(deviceObject);
}
}
革命尚未成功,以上只是.sys驅(qū)動的代碼實(shí)現(xiàn),主要目的是獲取Ring0權(quán)限,為了給開發(fā)者使用,需要做一個DLL提供對外的接口。請參閱第二篇。。。
到了這里,關(guān)于第一篇 windows驅(qū)動之WinRing0.sys的開發(fā)及使用(電腦溫度監(jiān)控軟件開發(fā))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!