昨天看了下在 应用层 与 驱动 进行通信的方法, 回想一下
1、CreateFile 打开设备
2、DeviceIoControl 发设备发送控制指令
3、CloseHandle 关闭设备
今天应该看下在 驱动.sys 需要做哪些东西,才可以在应用层使用 "设备路径" 来访问了
首先写一个不能再简单的驱动先!
simpledriver.c
#define DEVICE_NAME L"\\SimpleDriver"
#define DEVICE_LINK_NAME L"\\SimpleDriver_Link"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
#pragma code_seg( " INIT " )
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uniNameString;
UNICODE_STRING uniLinkString;
DEVICE_OBJECT *pCDO = NULL;
KdPrint(("SimpleDriver!DriverEntry \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_NAME);
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);
if( !NT_SUCCESS(status) )
return status;
RtlInitUnicodeString(&uniLinkString, DEVICE_LINK_NAME);
status = IoCreateSymbolicLink(&uniLinkString, &uniNameString);
if(!NT_SUCCESS(status))
return status;
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
#pragma code_seg( " PAGE " )
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING uniNameString;
PAGED_CODE();
KdPrint(("SimpleDriver!DriverUnload \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_LINK_NAME);
IoDeleteSymbolicLink(&uniNameString);
IoDeleteDevice(DriverObject->DeviceObject);
}
#pragma code_seg()
sources
TARGETPATH = OBJ
TARGETTYPE = DRIVER
SOURCES = simpledriver.c \
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
为了让 应用层 可以用 DeviceIoControl() 与应用程序通信,我们需要在 DriverEntry() 里设置
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
{
NTSTATUS status = STATUS_SUCCESS;
ULONG nIoCtrlCodes = 0; // IO控制码
PIO_STACK_LOCATION IrpStack = NULL; //IRP堆栈
KdPrint(("SimpleDriver!DeviceControl \n"));
//得到当前调用者的IRP
IrpStack = IoGetCurrentIrpStackLocation(Irp);
nIoCtrlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
KdPrint(("SimpleDriver!DeviceControl IoControlCode = %d\n", nIoCtrlCodes));
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
应用层的代码为:
#include < winioctl.h >
#include < stdio.h >
BOOL talkWithDriver()
{
HANDLE hDevice;
BOOL bResult;
DWORD junk;
hDevice = CreateFile("\\SimpleDriver", // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile Error ErrCode = %d", ::GetLastError());
return (FALSE);
}
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
NULL, 0, // no input buffer
NULL, 0, // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if ( !bResult )
{
printf("CreateFile Error ErrCode = %d", ::GetLastError());
return FALSE;
}
CloseHandle(hDevice);
return (bResult);
}
int main( int argc, char * argv[])
{
talkWithDriver ();
return 0;
}
编译后的驱动 .sys 用 OSRLOADER.exe 工具加载成功
运行应用层的 .exe 时,则显示 CreateFile Error ErrCode = 2
找不到路径
尝试将应用层的CreateFile 的路径改为
\\SimpleDriver
\\\\SimpleDriver
\\\\.\\SimpleDriver
还是显示 CreateFile Error ErrCode = 2
CreateFile 打开失败的原因未知!编译后的驱动 .sys 用 OSRLOADER.exe 工具加载成功
运行应用层的 .exe 时,则显示 CreateFile Error ErrCode = 2
找不到路径
尝试将应用层的CreateFile 的路径改为
\\\\SimpleDriver
\\\\.\\SimpleDriver
\\\\.\\SimpleDriver:
\\SimpleDriver
\\.\\SimpleDriver
结果还是显示 CreateFile Error ErrCode = 2
Google到了一个驱动的例子,按照例子里面的路径修改了一下
sys修改为:
#define DEVICE_NAME L"\\DosDevices\\SimpleDriver"
app修改为:
CreateFile("\\\\.\\SimpleDriver"
结果 CreateFile 调用后,GetLastErrorCode 得到的是 1, (Incorrect function. )
再次 Google 才知道,需要写 IRP_MJ_CREATE 例程,才可以 CreateFile 成功
于是把代码改了一下
.sys 代码
#define DEVICE_NAME L"\\DosDevices\\SimpleDriver"
#define DEVICE_LINK_NAME L"\\SimpleDriver_Link"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
#pragma code_seg( " INIT " )
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uniNameString;
UNICODE_STRING uniLinkString;
DEVICE_OBJECT *pCDO = NULL;
KdPrint(("SimpleDriver!DriverEntry \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_NAME);
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);
if( !NT_SUCCESS(status) )
return status;
RtlInitUnicodeString(&uniLinkString, DEVICE_LINK_NAME);
status = IoCreateSymbolicLink(&uniLinkString, &uniNameString);
if(!NT_SUCCESS(status))
return status;
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
return STATUS_SUCCESS;
}
#pragma code_seg( " PAGE " )
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING uniNameString;
PAGED_CODE();
KdPrint(("SimpleDriver!DriverUnload \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_LINK_NAME);
IoDeleteSymbolicLink(&uniNameString);
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PAGED_CODE();
KdPrint(("SimpleDriver!DeviceCreateClose \n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG nIoCtrlCodes = 0; // IO控制码
PIO_STACK_LOCATION IrpStack = NULL; //IRP堆栈
KdPrint(("SimpleDriver!DeviceControl \n"));
//得到当前调用者的IRP
IrpStack = IoGetCurrentIrpStackLocation(Irp);
nIoCtrlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
KdPrint(("SimpleDriver!DeviceControl IoControlCode = 0x%X\n", nIoCtrlCodes));
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
#pragma code_seg()
应用层 exe 代码
#include < winioctl.h >
#include < stdio.h >
BOOL talkWithDriver()
{
HANDLE hDevice;
BOOL bResult;
DWORD junk;
hDevice = CreateFile("\\\\.\\SimpleDriver", // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("\\\\.\\SimpleDriver CreateFile Error ErrCode = %d", ::GetLastError());
return (FALSE);
}
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
NULL, 0, // no input buffer
NULL, 0, // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if ( !bResult )
{
printf("DeviceIoControl Error ErrCode = %d", ::GetLastError());
return FALSE;
}
if( !CloseHandle(hDevice) );
{
printf("CloseHandle Error ErrCode = %d", ::GetLastError());
return FALSE;
}
return (bResult);
}
int main( int argc, char * argv[])
{
talkWithDriver ();
return 0;
}
重新用 OSRLOADER.exe 加载驱动,终于 CreateFile 成功了
Windbg 调试显示
SimpleDriver!DriverEntry
SimpleDriver!DeviceCreateClose
SimpleDriver!DeviceControl
SimpleDriver!DeviceControl IoControlCode = 0x70000
SimpleDriver!DeviceCreateClose
SimpleDriver!DriverUnload
但让我奇怪的是
应用层显示:
CloseHandle Error ErrCode = 0
CloseHandle 返回 FALSE, 但 GetLastError 得到的是 0
1、驱动层与应用层 的设备路径是如何对应的?
驱动层创建的设备路径是 \\DosDevices\\SimpleDriver
而对应的应用层的路径是 \\\\.\\SimpleDriver
为何会跟驱动层的不一致?
-- Thx 网友 Bill Gates
你完全理解错了device name和symbolic link name的意义。
用winobj看下你机器上的kernel namespace。
应用层如果用CreateFile,只能访问到\\??下的路径。如果用ZwCreateFile,可以访问整个命名空间。
2、CloseHandle() 为何会调用失败,而返回的 LastErrorCode 为0 ?
-- 未解决