1.특징
-양방향 전달이 가능하다. (커널 <-> 유저)
<->단방향 통신
>ReadFile
>WriteFile
2.컨트롤 코드
-버퍼 전달 형식 등을 설정할 수 있음.
-CTL_CODE() 메크로를 이용하여 간단히 설정 가능.
#define IOCTL_TEST_N CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_NEITHER,FILE_ANY_ACCESS)
#define IOCTL_TEST_B CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_BUFFERED,FILE_ANY_ACCESS)
3.순서
0)커널] 디바이스 오브젝트 생성.
1)커널] 심볼릭 링크 설정.
2)유저] CreateFile(심볼릭 링크)로 드라이버 핸들 open.
3)유저] DeviceIoControl로 in, out 인자, ioctrl 전달 후 호출
4)커널] 컨트롤 코드를 이용하여 요청을 구분, 구분한 뒤 코드에 맞는 다른 응답을 처리.
5)유저] DeviceIoControl 리턴.
4. 코드
//유저
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#define IOCTL_TEST_N CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_NEITHER,FILE_ANY_ACCESS)
#define IOCTL_TEST_B CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main(void)
{
HANDLE dHandle;
WCHAR deviceLink[] = L"\\\\.\\woounnan";
DWORD retLen;
char sendMsg[] = "hi!!!!\n";
char buf[100] = { 0 };
dHandle = CreateFileW(
deviceLink,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (dHandle == INVALID_HANDLE_VALUE)
{
printf("Get Device Handle Fail! : 0x%X \n", GetLastError());
_getch();
return 1;
}
if (!DeviceIoControl(dHandle, IOCTL_TEST_N, (LPVOID) buf, sizeof(buf), sendMsg, sizeof(sendMsg), &retLen, 0))
{
printf("DeviceIOControl Fail!! \n");
_getch();
CloseHandle(dHandle);
return 1;
}
printf("recv msg:%s\n", buf);
printf("size:%d\n", retLen);
CloseHandle(dHandle);
return 0;
}
//커널
#include <ntddk.h>
#include <string.h>
#define LINK_NAME L"\\DosDevices\\woounnan"
#define DEVICE_NAME L"\\Device\\woounnan"
#define IOCTL_TEST_N CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_NEITHER,FILE_ANY_ACCESS)
#define IOCTL_TEST_B CTL_CODE(FILE_DEVICE_UNKNOWN,0x4000,METHOD_BUFFERED,FILE_ANY_ACCESS)
PDEVICE_OBJECT MyDevice;
UNICODE_STRING DeviceLink;
UNICODE_STRING DeviceName;
NTSTATUS MyIOControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION pStack;
NTSTATUS returnStatus = STATUS_SUCCESS;
ULONG ControlCode;
PCHAR outBuf;
//PCHAR data = "ah ssibal";
pStack = IoGetCurrentIrpStackLocation(Irp);
ControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
switch (ControlCode)
{
case IOCTL_TEST_N:
DbgPrintEx(DPFLTR_ACPI_ID, 0, "\n IOCTL_TEST Call~~ \n");
DbgPrintEx(DPFLTR_ACPI_ID, 0, "recv:%d %d\n", pStack->Parameters.DeviceIoControl.InputBufferLength, pStack->Parameters.DeviceIoControl.OutputBufferLength);
DbgPrintEx(DPFLTR_ACPI_ID, 0, "recv:%s \n", Irp->UserBuffer);
outBuf = pStack->Parameters.DeviceIoControl.Type3InputBuffer;
//(PCHAR)Irp->AssociatedIrp.SystemBuffer;
//memcpy(outBuf, "test", 4);
memcpy(outBuf, "test", 4);
DbgPrintEx(DPFLTR_ACPI_ID, 0, "outbuf:%s\nsystembuf:%s\n", outBuf, pStack->Parameters.DeviceIoControl.Type3InputBuffer);
Irp->IoStatus.Information = 19;
break;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return returnStatus;
}
NTSTATUS myCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
IoDeleteDevice(MyDevice);
IoDeleteSymbolicLink(&DeviceLink);
DbgPrintEx(DPFLTR_ACPI_ID, 0, "Unloding driver \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS returnStatus = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(RegistryPath);
RtlInitUnicodeString(&DeviceLink, LINK_NAME);
RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
DbgPrintEx(DPFLTR_ACPI_ID, 0, "Loading driver\n");
returnStatus = IoCreateDevice(
DriverObject,
0,
&DeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&MyDevice
);
// DEVICE_OBJECT의 초기화가 끝났다
MyDevice->Flags &= ~DO_DEVICE_INITIALIZING;
MyDevice->Flags |= DO_BUFFERED_IO;
if (!NT_SUCCESS(returnStatus))
{
//DbgPrint("IoCreateDevice Fail! \n");
return returnStatus;
}
//DbgPrint("Success IoCreateDevice \n");
returnStatus = IoCreateSymbolicLink(&DeviceLink, &DeviceName);
if (!NT_SUCCESS(returnStatus))
{
//DbgPrint("IoCreateSymbolicLink Fail! \n");
return returnStatus;
}
//DbgPrint("Success IoCreateSymbolicLink \n");
DriverObject->DriverUnload = OnUnload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIOControl;
DriverObject->MajorFunction[IRP_MJ_CREATE] = myCreate;
return returnStatus;
}