응용 프로그램 과 드라이버 통신 DeviceIoControl
15254 단어 DeviceIoControl커 뮤 니 케 이 션드라이버
사실 일종 의 통신 협의 로 볼 수 있다
CTL 봐 봐.CODE 원형:
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
이 매크로 네 개의 매개 변 수 는 자 연 스 럽 게 32 비트 가 4 부분 으로 나 뉘 어 있 고 높이 16 비트 저장 장치 유형,14~15 비트 접근 권한,2~13 비트 조작 기능,마지막 0,1 두 비트 는 버퍼 가 어떻게 I/O 와 파일 시스템 데이터 버퍼 와 데이터 전달 방식 을 하 는 지 확인 하 는 것 입 니 다.가장 흔히 볼 수 있 는 것 은 METHOD 입 니 다.BUFFERED。사용자 정의 CTLCODE:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
IOCTL_Device_Function:생 성 된 IRP 의 MinorFunction
DeviceType:장치 대상 의 유형 입 니 다.장치 종류 참고:http://blog.csdn.net/liyun123gx/article/details/38058965
Function:사용자 정의 IO 제어 코드 입 니 다.자신 이 정의 할 때 0x 800 에서 0xFFF 를 가 져 옵 니 다.왜냐하면 0x0 에서 0x7FF 는 마이크로소프트 가 보류 하기 때 문 입 니 다.
Method:데이터 조작 모드.
METHOD_BUFFERED:버퍼 모드
METHOD_IN_DIRECT:직접 쓰기 모드
METHOD_OUT_DIRECT:직접 읽 기 모드
METHOD_NEITHER:Neither 모드
Access:접근 권한,가 치 는 다음 과 같 습 니 다.
FILE_ANY_ACCESS:사용자 가 모든 권한 을 가지 고 있 음 을 나타 낸다.
FILE_READ_DATA:읽 기 전용 권한 표시
FILE_WRITE_DATA:쓰기 권한 표시
할 수 있어 FILEWRITE_DATA | FILE_READ_DATA:읽 기 및 쓰기 권한 을 표시 하지만 FILE 에 미 치지 못 했 습 니 다.ANY_ACCESS 권한.
이 버퍼 의 데이터 전달 방식 방법 을 계속 소개 합 니 다.
Method 는 Ring 3/Ring 0 의 통신 중의 메모리 접근 방식 을 나타 내 는데 네 가지 방식 이 있다.
#defineMETHOD_BUFFERED0
#defineMETHOD_IN_DIRECT1
#defineMETHOD_OUT_DIRECT2
#defineMETHOD_NEITHER3
(1)METHOD 를 사용 하면BUFFERED 는 시스템 이 사용자 의 입 출력 을 pIrp->Associated Irp.SystemBuffer 를 통 해 버퍼 링 하기 때문에 이런 방식 의 통신 이 비교적 안전 하 다 는 것 을 나타 낸다.
METHOD_BUFFERED 방식 은 Ring 3 의 입 출력 을 모두 버퍼 링 한 셈 이다.
METHOD_BUFFERED 방식:
(2)METHOD 를 사용 하면IN_DIRECT 또는 METHODOUT_DIRECT 방식 은 시스템 이 입력 버퍼 를 pIrp->Associated Irp.SystemBuffer 에 고정 시 키 고 출력 버퍼 를 잠 근 다음 커 널 모드 에서 주 소 를 다시 표시 하 는 것 도 안전 하 다 는 것 을 나타 낸다.
METHOD_IN_DIRECT 와 METHODOUT_DIRECT 는'직접 방식'이 라 고 할 수 있 으 며,시스템 이 여전히 Ring 3 의 입력 버퍼 를 버퍼 링 하지만 Ring 3 의 출력 버퍼 는 버퍼 링 없 이 커 널 에 잠 겨 있 는 것 을 말한다.이렇게 Ring 3 출력 버퍼 는 드라이버 가 I/O 요청 을 완료 하기 전에 접근 할 수 없 으 며 어느 정도 안전성 을 보장 합 니 다.
Ring 3 에 대한 입력 버퍼 와 METHODBUFFERED 방식 은 일치 합 니 다.Ring 3 의 출력 버퍼 에 대해 서 는 먼저 시스템 에 의 해 잠 겨 있 고 pIrp->MdlAddress 를 사용 하여 이 메모 리 를 설명 합 니 다.드라이버 는 MmGetSystem Address ForMdlSafe 함 수 를 사용 하여 이 메모 리 를 커 널 메모리 주소(OutputBuffer)에 투사 한 다음 에 OutputBuffer 주 소 를 직접 기록 할 수 있 습 니 다.마지막 으로 구동 파견 루틴 을 되 돌려 준 후에 시스템 에서 이 메모리 의 잠 금 을 해제 할 수 있 습 니 다.
METHOD_IN_DIRECT 와 METHODOUT_DIRECT 방식 의 메모리 접근
METHOD_IN_DIRECT 와 METHODOUT_DIRECT 방식 의 차 이 는 장 치 를 열 수 있 는 권한 에 만 있 습 니 다.읽 기 전용 권한 으로 장 치 를 열 때 METHODIN_DIRECT 방식 의 IoControl 은 성공 하고 METHOD 는OUT_DIRECT 방식 은 실패 합 니 다.읽 기와 쓰기 권한 으로 장 치 를 열 면 두 가지 방식 이 성공 합 니 다.
METHOD_IN_DIRECT 와 METHODOUT_DIRECT 방식:
(3)METHOD 를 사용 하면NEITHER 방식,'기타 방식'은 통신 의 효율 성 이 높 아 졌 지만 안전 하지 않다.구동 하 는 파견 함수 에 버퍼 를 입력 하면 I/O 스 택(IOSTACK_LOCATION)의 stack->Parameters.deviceIo Control.Type3InputBuffer 를 받 았 습 니 다.출력 버퍼 는 pIrp->UserBuffer 를 통 해 얻 을 수 있 습 니 다.구동 중의 파견 함 수 는 전 달 된 사용자 의 입력 과 출력 주 소 를 보장 할 수 없 기 때문에 이 주 소 를 쓰 는 버퍼 를 직접 읽 지 않 는 것 이 좋다.읽 기와 쓰기 전에 Probe ForRead 와 Probe ForWrite 함 수 를 사용 하여 주 소 를 읽 을 수 있 고 쓸 수 있 는 지 확인 해 야 합 니 다.
METHOD_ NEITHER 방식 은 버퍼 링 을 하지 않 습 니 다.드라이버 에서 Ring 3 의 입 출력 메모리 주 소 를 직접 사용 할 수 있 습 니 다.
드라이버 는 pIrpStack->Parameters.deviceIoControl.Type3InputBuffer 를 통 해 Ring 3 의 입력 버퍼 주 소 를 얻 을 수 있 습 니 다(그 중에서 pIrpStack 은 IoGetCurrent IrpStack Location(pIrp)의 반환 입 니 다).pIrp->UserBuffer 를 통 해 Ring 3 의 출력 버퍼 주 소 를 얻 을 수 있 습 니 다.
METHOD 때문에NEITHER 방식 은 안전 하지 않 으 므 로 Type3InputBuffer 가 읽 기 전에 Probe ForRead 함 수 를 사용 하여 탐지 하고 UserBuffer 가 쓰기 전에 Probe ForWrite 함 수 를 사용 하여 탐지 한 다음 이상 이 발생 하지 않 았 을 때 읽 기 및 쓰기 작업 을 하 는 것 이 좋 습 니 다.
METHOD_NEITHER 방식:
2.드라이버 이름,심 볼 릭 링크 이름 정의
IO 제어 코드 CTL 정의 되 었 습 니 다.CODE,두 번 째 드라이버 는 드라이버 이름과 심 볼 릭 링크 이름 도 준비 해 야 합 니 다.
Ring 0 층 에서 드라이버 이름 을 설정 하 는 동시에 기호 링크 이름 을 설정 해 야 하 는 이 유 는 기호 링크 이름 만 사용자 모드 에서 응용 프로그램 에 의 해 인식 되 기 때문이다.
windows 의 장 치 는'\Device\[장치 이름]'형식 으로 명명 되 었 다.
예 를 들 어 디스크 파 티 션 의 c 디스크,d 디스크 의 장치 이름 은'\Device\HarddiskVolume 1','\Device\HarddiskVolume 2'입 니 다.물론 장치 이름 을 지정 하지 않 아 도 됩 니 다.
IoCreateDevice 에 장치 이름 이 지정 되 어 있 지 않 으 면 I/O 관리 자 는 자동 으로 장치 이름 으로 숫자 를 할당 합 니 다.
예 를 들 어"\\Device\0000001".\Device\\[장치 이름]은 기억 하기 쉽 지 않 습 니 다.보통 심 볼 릭 링크 는 장치 의 별명 으로 이해 할 수 있 습 니 다.더 중요 한 것 은 장치 이름 입 니 다.커 널 모드 의 다른 드라이버 에 의 해 만 인식 되 고 별명 은 사용자 모드 에서 의 응용 프로그램 에 의 해 식별 될 수 있 습 니 다.예 를 들 어 c 디스크 는'c:'라 는 심 볼 릭 링크 입 니 다.그 진정한 장치 대상 은'\Device\HarddiskVolume 1'입 니 다.그래서 드라이버 를 쓸 때 보통 우 리 는 심 볼 릭 링크 를 만 듭 니 다.드라이버 에 사용 되 지 않 더 라 도 이것 은 좋 은 습관 이 라 고 할 수 있 습 니 다.
구동 중 심 볼 릭 링크 이름 은 이렇게 쓰 여 있 습 니 다.
L"\\??\\HelloDDK" --->\??\HelloDDK
혹은
L"\\DosDevices\\HelloDDK"--->\DosDevices\HelloDDK
응용 프로그램 에서 심 볼 릭 링크 이름:
L"\\\\.\\HelloDDK"-->\\.\HelloDDK
DosDevices 의 심 볼 릭 링크 이름 은??,그래서'\\DosDevice\\XXXX'는 바로\\??\\XXXX
#define DEVICE_OBJECT_NAME L"\\Device\\BufferedIODeviceObjectName"
//
#define DEVICE_LINK_NAME L"\\DosDevices\\BufferedIODevcieLinkName"
// Ring3
3.기호 링크 이름과 장치 대상 이름 을 연결 하고 IO 제어 코드 를 기다린다.드라이버 가 해 야 할 마지막 단 계 는 먼저 IoCreate Device 함수 로 장치 대상 을 만 든 다음 에 IoCreate SymbolicLink 로 기호 링크 이름 을 장치 대상 이름과 연결 시 켜 큰 성 과 를 거 두 었 고 IO 제어 코드 를 기다 리 고 있 습 니 다.
//
RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
//
Status = IoCreateDevice(DriverObject,NULL,
&DeviceObjectName,
FILE_DEVICE_UNKNOWN,
0, FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
//
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
//
Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
return Status;
}
4.응용 프로그램 이 장치 핸들 을 가 져 오고 IO 제어 코드 를 보 냅 니 다.드라이버 패드 를 다 듬 은 후에 응용 프로그램 은 심 볼 릭 링크 이름 으로 Create File 함 수 를 통 해 장치 핸들 DeviceHandle 을 얻 고 이 필드 의 주인공 을 사용 할 수 있 습 니 다.DeviceIoControl 은 이 DeviceHandle 을 통 해 제어 코드 를 보 낼 수 있 습 니 다.
먼저 이 두 함 수 를 보 세 요.
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice, //CreateFile
_In_ DWORD dwIoControlCode,//
_In_opt_ LPVOID lpInBuffer, //
_In_ DWORD nInBufferSize, //
_Out_opt_ LPVOID lpOutBuffer, //
_In_ DWORD nOutBufferSize, //
_Out_opt_ LPDWORD lpBytesReturned, // , pIrp->IoStatus.Information。
_Inout_opt_ LPOVERLAPPED lpOverlapped // 。 NULL,DeviceIoControl ; ,
);
HANDLE CreateFile(
LPCTSTR lpFileName, //
DWORD dwDesiredAccess, //
DWORD dwShareMode, //
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //
DWORD dwCreationDisposition, //
DWORD dwFlagsAndAttributes, // ( 、 、 、 )
HANDLE hTemplateFile //
);
5.DeviceIoControl 의 통신 절 차 를 정리 합 니 다.1.드라이버 와 응용 프로그램 이 IO 제어 코드 를 사용자 정의(CTLCODE 매크로 4 개의 매개 변수,32 비트,4 부분,저장 장치 유형,접근 권한,조작 기능,버퍼 데이터 전달 방식(4 가지)
2.드라이버 는 드라이버 이름,심 볼 릭 링크 이름 을 정의 하고 심 볼 릭 링크 이름 을 장치 대상 이름과 연결 시 켜 IO 제어 코드(IoCreateDevice,IoCreateSymbolicLink)를 기다린다.
3.응용 프로그램 은 심 볼 릭 링크 이름 으로 CreateFile 함 수 를 통 해 장치 핸들 DeviceHandle 을 가 져 오고 이 필드 의 주인공 을 사용 합 니 다.DeviceIoControl 은 이 장치 핸들 을 통 해 제어 코드 를 파견 함수 에 보 냅 니 다.
소스 코드
BufferedIO.h
#pragma once
#include <ntifs.h>
#define CTL_SYS \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define DEVICE_OBJECT_NAME L"\\Device\\BufferedIODeviceObjectName"
//
#define DEVICE_LINK_NAME L"\\DosDevices\\BufferedIODevcieLinkName"
// Ring3
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
BufferedIO.c
#include "BufferedIO.h"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING DeviceObjectName;
UNICODE_STRING DeviceLinkName;
ULONG i;
//
//
// (global Static Const)
DriverObject->DriverUnload = DriverUnload;
//
RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
//
Status = IoCreateDevice(DriverObject,NULL,
&DeviceObjectName,
FILE_DEVICE_UNKNOWN,
0, FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
//
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
//
Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
return Status;
}
//
for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
DriverObject->MajorFunction[i] = PassThroughDispatch; //
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch;
return Status;
}
//
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS; //LastError()
Irp->IoStatus.Information = 0; //ReturnLength
IoCompleteRequest(Irp, IO_NO_INCREMENT); // Irp Io
return STATUS_SUCCESS;
}
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
ULONG_PTR Informaiton = 0;
PVOID InputData = NULL;
ULONG InputDataLength = 0;
PVOID OutputData = NULL;
ULONG OutputDataLength = 0;
ULONG IoControlCode = 0;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Irp
IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
InputData = Irp->AssociatedIrp.SystemBuffer;
OutputData = Irp->AssociatedIrp.SystemBuffer;
InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
switch (IoControlCode)
{
case CTL_SYS:
{
if (InputData != NULL&&InputDataLength > 0)
{
DbgPrint("%s\r
", InputData);
}
if (OutputData != NULL&&OutputDataLength >= strlen("Ring0->Ring3") + 1)
{
memcpy(OutputData, "Ring0->Ring3", strlen("Ring0->Ring3") + 1);
Status = STATUS_SUCCESS;
Informaiton = strlen("Ring0->Ring3") + 1;
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES; //
Informaiton = 0;
}
break;
}
default:
break;
}
Irp->IoStatus.Status = Status; //Ring3 GetLastError();
Irp->IoStatus.Information = Informaiton;
IoCompleteRequest(Irp, IO_NO_INCREMENT); // Irp Io
return Status; //Ring3 DeviceIoControl()
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DeviceLinkName;
PDEVICE_OBJECT v1 = NULL;
PDEVICE_OBJECT DeleteDeviceObject = NULL;
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
IoDeleteSymbolicLink(&DeviceLinkName);
DeleteDeviceObject = DriverObject->DeviceObject;
while (DeleteDeviceObject != NULL)
{
v1 = DeleteDeviceObject->NextDevice;
IoDeleteDevice(DeleteDeviceObject);
DeleteDeviceObject = v1;
}
}
IO.cpp
// IO.cpp : 。
//
#include "stdafx.h"
#include <windows.h>
#define DEVICE_LINK_NAME L"\\\\.\\BufferedIODevcieLinkName"
#define CTL_SYS \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
HANDLE DeviceHandle = CreateFile(DEVICE_LINK_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (DeviceHandle==INVALID_HANDLE_VALUE)
{
return 0;
}
char BufferData = NULL;
DWORD ReturnLength = 0;
BOOL IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
"Ring3->Ring0",
strlen("Ring3->Ring0")+1,
(LPVOID)BufferData,
0,
&ReturnLength,
NULL);
if (IsOk == FALSE)
{
int LastError = GetLastError();
if (LastError == ERROR_NO_SYSTEM_RESOURCES)
{
char BufferData[MAX_PATH] = { 0 };
IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
"Ring3->Ring0",
strlen("Ring3->Ring0") + 1,
(LPVOID)BufferData,
MAX_PATH,
&ReturnLength,
NULL);
if (IsOk == TRUE)
{
printf("%s\r
", BufferData);
}
}
}
if (DeviceHandle != NULL)
{
CloseHandle(DeviceHandle);
DeviceHandle = NULL;
}
printf("Input AnyKey To Exit\r
");
getchar();
return 0;
}
이상 은 응용 프로그램 과 드라이버 통신 DeviceIoControl 의 상세 한 내용 입 니 다.응용 프로그램 드라이버 통신 DeviceIoControl 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
웹 기반 실시 간 통신 방안전통 적 인 웹 방식 은 클 라 이언 트 가 요청 을 하고 서버 측 응답 방식 으로 작 동 하지만 실제 응용 에서 클 라 이언 트 는 서버 와 지속 적 인 업 데 이 트 를 유지 해 야 합 니 다. 이 응용 프로그램...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.