#include "Driver.h"
// Предварительные объявления функций:
NTSTATUS DeviceControlRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp );
VOID UnloadRoutine(IN PDRIVER_OBJECT DriverObject);
NTSTATUS ReadWrite_IRPhandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp );
NTSTATUS Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
extern "C"
NTSTATUS Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
#if DBG
DbgPrint("-Primer- In Close handler.");
#endif
return CompleteIrp(Irp,STATUS_SUCCESS,0);
}
// Хотя и нехорошо делать глобальные переменные в драйвере...
KSPIN_LOCK MySpinLock;
#pragma code_seg("INIT") // начало секции INIT
extern "C"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, //об'єкт драйвера, містить покажчики на всі необхідні операційній системі функції, які ми повинні будемо ініціювати.
IN PUNICODE_STRING RegistryPath ) //ім'я розділу в реєстрі, де зберігається інформація про даний драйвер.
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT fdo;
UNICODE_STRING devName;
#if DBG
DbgPrint("=Example= In DriverEntry.");
DbgPrint("=Example= RegistryPath = %ws.", RegistryPath->Buffer);
#endif
// DriverObject->DriverExtension->AddDevice= OurAddDeviceRoutine;
DriverObject->DriverUnload = UnloadRoutine;
DriverObject->MajorFunction[IRP_MJ_CREATE]= Create_File_IRPprocessing;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Close_HandleIRPprocessing;
DriverObject->MajorFunction[IRP_MJ_READ] = ReadWrite_IRPhandler;
DriverObject->MajorFunction[IRP_MJ_WRITE] = ReadWrite_IRPhandler;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= DeviceControlRoutine;
//========================================================
RtlInitUnicodeString( &devName, L"\\Device\\EXAMPLE" );
// Создаем наш Functional Device Object (FDO) и получаем
// указатель на созданный FDO в нашей переменной fdo.
status = IoCreateDevice(DriverObject,
sizeof(EXAMPLE_DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fdo);
if(!NT_SUCCESS(status)) return status;
PEXAMPLE_DEVICE_EXTENSION dx = (PEXAMPLE_DEVICE_EXTENSION)fdo->DeviceExtension;
dx->fdo = fdo;
#if DBG
DbgPrint("=Example= FDO %X, DevExt=%X.",fdo,dx);
#endif
//=======================================
UNICODE_STRING symLinkName;
#define SYM_LINK_NAME L"\\DosDevices\\Example"
RtlInitUnicodeString(
&symLinkName,
SYM_LINK_NAME );
dx->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName, &devName );
if (!NT_SUCCESS(status))
{ // при неудаче √ удалить Device Object и вернуть управление
IoDeleteDevice( fdo );
return status;
}
KeInitializeSpinLock(&MySpinLock);
#if DBG
DbgPrint("=Example= DriverEntry successfully completed.");
#endif
return status;
}
#pragma code_seg() // end INIT section
extern "C"
NTSTATUS CompleteIrp( PIRP Irp, NTSTATUS status, ULONG info)
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;//Параметр info, если он не равен нулю, чаще всего содержит число байт, переданных клиенту (полученных от клиента) драйвера
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
extern "C"
NTSTATUS ReadWrite_IRPhandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp )
{
ULONG BytesTxd = 0;
NTSTATUS status = STATUS_SUCCESS; //Завершение с кодом status
// Задаем печать отладочных сообщений √ если сборка отладочная
#if DBG
DbgPrint("-Example- in ReadWrite_IRPhandler.");
#endif
return CompleteIrp(Irp,status,BytesTxd);
}
extern "C"
NTSTATUS Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
// Задаем печать отладочных сообщений - если сборка отладочная
#if DBG
DbgPrint("-Example- Create File is %ws",
&(IrpStack->FileObject->FileName.Buffer));
#endif
return CompleteIrp(Irp,STATUS_SUCCESS,0); // Успешное завершение
}
extern "C"
NTSTATUS DeviceControlRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp )
{
NTSTATUS status = STATUS_SUCCESS;
ULONG BytesTxd =0;
PIO_STACK_LOCATION IrpStack=IoGetCurrentIrpStackLocation(Irp);
PEXAMPLE_DEVICE_EXTENSION dx =
(PEXAMPLE_DEVICE_EXTENSION)fdo->DeviceExtension;
//-------------------------------
ULONG ControlCode =
IrpStack->Parameters.DeviceIoControl.IoControlCode;
ULONG method = ControlCode & 0x03;
KIRQL irql,
currentIrql = KeGetCurrentIrql();
#if DBG
DbgPrint("-Example- In DeviceControlRoutine (fdo= %X)\n",fdo);
DbgPrint("-Example- DeviceIoControl: IOCTL %x.", ControlCode );
if(currentIrql==PASSIVE_LEVEL)
DbgPrint("-Example- PASSIVE_LEVEL (val=%d)",currentIrql);
#endif
KeAcquireSpinLock(&MySpinLock,&irql);
switch( ControlCode) {
#ifndef SMALL_VERSION
case IOCTL_PRINT_DEBUG_MESS:
{
#if DBG
DbgPrint("-Example- IOCTL_PRINT_DEBUG_MESS.");
#endif
break;
}
case IOCTL_CHANGE_IRQL:
{
#if DBG
DbgPrint("-Example- IOCTL_CHANGE_IRQL.");
KIRQL dl = DISPATCH_LEVEL,
oldIrql,
newIrql=25;
KeRaiseIrql(newIrql,&oldIrql);
newIrql=KeGetCurrentIrql();
DbgPrint("-Example- DISPATCH_LEVEL value =%d",dl);
DbgPrint("-Example- IRQLs are old=%d new=%d",
oldIrql,newIrql);
KeLowerIrql(oldIrql);
#endif
break;
}
#endif
case IOCTL_MAKE_SYSTEM_CRASH:
{
int errDetected=0;
char x = (char)0xFF;
#if DBG
DbgPrint("-Example- IOCTL_MAKE_SYSTEM_CRASH.");
#endif
__try {
x = *(char*)0x0L;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
errDetected=1;
};
#if DBG
DbgPrint("-Example- Value of x is %X.",x);
if(errDetected)
DbgPrint("-Example- Except detected in Example driver.");
#endif
break;
}
#ifndef SMALL_VERSION
case IOCTL_TOUCH_PORT_378H:
{
unsigned short ECRegister = 0x378+0x402;
#if DBG
DbgPrint("-Example- IOCTL_TOUCH_PORT_378H.");
#endif
_asm {
mov dx,ECRegister ;
xor al,al ;
out dx,al ; Установить EPP mode 000
mov al,095h ; Биты 7:5 = 100
out dx,al ; Установить EPP mode 100
}
//
break;
}
case IOCTL_SEND_BYTE_TO_USER:
{
ULONG InputLength =
IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength =
IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
#if DBG
DbgPrint("-Example- Buffer outlength %d",OutputLength);
#endif
if( OutputLength<1 )
{
status = STATUS_INVALID_PARAMETER;
break;
}
UCHAR *buff;
if(method==METHOD_BUFFERED)
{
buff = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
#if DBG
DbgPrint("-Example- Method : BUFFERED.");
#endif
}
else
if (method==METHOD_NEITHER)
{
buff=(unsigned char*)Irp->UserBuffer;
#if DBG
DbgPrint("-Example- Method : NEITHER.");
#endif
}
else
{
#if DBG
DbgPrint("-Example- Method : unsupported.");
#endif
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
#if DBG
DbgPrint("-Example- Buffer address is %08X",buff);
#endif
*buff=33;
BytesTxd = 1;
break;
}
#endif
default: status = STATUS_INVALID_DEVICE_REQUEST;
}
KeReleaseSpinLock(&MySpinLock,irql);
#if DBG
DbgPrint("-Example- DeviceIoControl: %d bytes written.", (int)BytesTxd);
#endif
return CompleteIrp(Irp,status,BytesTxd);
}
#pragma code_seg("PAGE")
extern "C"
VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextDevObj;
int i;
#if DBG
DbgPrint("-Example- In Unload Routine.");
#endif
//==========================================================
pNextDevObj = pDriverObject->DeviceObject;
for(i=0; pNextDevObj!=NULL; i++)
{
PEXAMPLE_DEVICE_EXTENSION dx =
(PEXAMPLE_DEVICE_EXTENSION)pNextDevObj->DeviceExtension;
UNICODE_STRING *pLinkName = & (dx->ustrSymLinkName);
pNextDevObj = pNextDevObj->NextDevice;
#if DBG
DbgPrint("-Example- Deleted device (%d) : pointer to FDO = %X.",
i,dx->fdo);
DbgPrint("-Example- Deleted symlink = %ws.", pLinkName->Buffer);
#endif
IoDeleteSymbolicLink(pLinkName);
IoDeleteDevice( dx->fdo);
}
}
#pragma code_seg()