#include <ntddk.h>


#define FILE_DEVICE_UNKNOWN             0x00000022
#define IOCTL_UNKNOWN_BASE              FILE_DEVICE_UNKNOWN
#define IOCTL_PROCOBSRV_ACTIVATE_MONITORING    \//создан собственный IOCTL запрос при помощи макроса CTL_CODE:
	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_PROCOBSRV_GET_PROCINFO    \
	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

void UnloadDriver(
	PDRIVER_OBJECT DriverObject
	);
NTSTATUS DispatchCreateClose(
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp
	);
NTSTATUS DispatchIoctl(
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp
	);
//
// Process function callback

VOID ProcessCallback(
	IN HANDLE  hParentId, 
	IN HANDLE  hProcessId, 
	IN BOOLEAN bCreate
	);
//
// Structure for holding info about activating/deactivating the driver

typedef struct _ActivateInfo
{
    BOOLEAN  bActivated;
} ACTIVATE_INFO, *PACTIVATE_INFO;

//
// Structure for process callback information

typedef struct _ProcessCallbackInfo
{
    HANDLE  hParentId;
    HANDLE  hProcessId;
    BOOLEAN bCreate;
} PROCESS_CALLBACK_INFO, *PPROCESS_CALLBACK_INFO;

//
// Private storage for process retreiving 

typedef struct _DEVICE_EXTENSION 
{
    PDEVICE_OBJECT DeviceObject;
	//
	// Shared section

    HANDLE  hProcessId;
	//
	// Process section data

    PKEVENT ProcessEvent;
    HANDLE  hParentId;
    BOOLEAN bCreate;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

//
// Global variables

PDEVICE_OBJECT g_pDeviceObject;
ACTIVATE_INFO  g_ActivateInfo;

//
// The main entry point of the driver module

NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT DriverObject, 
	IN PUNICODE_STRING RegistryPath
	)
{
    NTSTATUS                  ntStatus;
    UNICODE_STRING            uszDriverString;
    UNICODE_STRING            uszDeviceString;
    UNICODE_STRING            uszProcessEventString;
    PDEVICE_OBJECT            pDeviceObject;
    PDEVICE_EXTENSION         extension;
	HANDLE                    hProcessHandle;

	//    
	// Point uszDriverString at the driver name

	//Начнем с определения структур UNICODE_STRING, описывающих имя устройства и символьной ссылки. Как я уже говорил в третьей части, ядро любит работать со строками именно в этом формате. 
    RtlInitUnicodeString(&uszDriverString, L"\\Device\\ProcObsrv");// Задача функции RtlInitUnicodeString измерить unicode-строку и заполнить 
	//
    // Create and initialize device object

    ntStatus = IoCreateDevice(//Для создания девайсов в Windows Kernel имеется всем известная API: IoCreateDevice(..., DEVICE_TYPE,...);
		DriverObject,
        sizeof(DEVICE_EXTENSION),
        &uszDriverString,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDeviceObject
		);
    if(ntStatus != STATUS_SUCCESS)
        return ntStatus;
    //
	// Assign extension variable

    extension = pDeviceObject->DeviceExtension;
    //
	// Point uszDeviceString at the device name

    RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\ProcObsrv");
    //
	// Create symbolic link to the user-visible name

    ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);

    if(ntStatus != STATUS_SUCCESS)
    {
		//
        // Delete device object if not successful

        IoDeleteDevice(pDeviceObject);
        return ntStatus;
    }
	//
    // Assign global pointer to the device object for use by the callback functions
	
    g_pDeviceObject = pDeviceObject;
	//
	// Setup initial state

	g_ActivateInfo.bActivated = FALSE;
	//
    // Load structure to point to IRP handlers

    DriverObject->DriverUnload                         = UnloadDriver;
    DriverObject->MajorFunction[IRP_MJ_CREATE]         = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
	//
    // Create event for user-mode processes to monitor

    RtlInitUnicodeString(
		&uszProcessEventString, 
		L"\\BaseNamedObjects\\ProcObsrvProcessEvent"
		);
    extension->ProcessEvent = IoCreateNotificationEvent(
		&uszProcessEventString, 
		&hProcessHandle
		);
	//
    // Clear it out
	//
    KeClearEvent(extension->ProcessEvent);
	//
    // Return success

    return ntStatus;
}

//
// Create and close routine

NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status      = STATUS_SUCCESS;//// Возращаемое значение - ошибка или нормальное. При нормальном завершении - будет передан HANDLE на устройство, в нашем случае на драйвер. 
    Irp->IoStatus.Information = 0;//// Количество переданных вверх байт - в нашем случае 0 потому как нет передаваемых параметров. 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);//// Завершение работы. Вызов функции IofCompleteRequest инициирует операцию завершения ввода-вывода (I/O completion). 
    return STATUS_SUCCESS;
}

//
// Process function callback

VOID ProcessCallback(
	IN HANDLE  hParentId, 
	IN HANDLE  hProcessId, 
	IN BOOLEAN bCreate
	)
{
	PDEVICE_EXTENSION extension;
	//
    // Assign extension variable

	extension = g_pDeviceObject->DeviceExtension;
	//
    // Assign current values into device extension.  
	// User-mode apps will pick it up using DeviceIoControl calls.

    extension->hParentId  = hParentId;
    extension->hProcessId = hProcessId;
    extension->bCreate    = bCreate;
	//
    // Signal the event thus the user-mode apps listening will be aware
    // that something interesting has happened.  

    KeSetEvent(extension->ProcessEvent, 0, FALSE);
    KeClearEvent(extension->ProcessEvent);
}

//
// IOCTL handler for setting the callback

NTSTATUS ActivateMonitoringHanlder(
	IN PIRP           Irp
	)
{
	NTSTATUS               ntStatus = STATUS_UNSUCCESSFUL;
	PIO_STACK_LOCATION     irpStack  = IoGetCurrentIrpStackLocation(Irp);
	PACTIVATE_INFO         pActivateInfo;
	
	if (irpStack->Parameters.DeviceIoControl.InputBufferLength >= 
	   sizeof(ACTIVATE_INFO))		
	{
		pActivateInfo = Irp->AssociatedIrp.SystemBuffer;
		if (g_ActivateInfo.bActivated != pActivateInfo->bActivated)
		{
			if (pActivateInfo->bActivated) 
			{
				//
				// Set up callback routines
		
				/*
				Добавляет/удаляет в системный список вызовов указатель на процедуру, которая будет вызываться всегда при создании или удалении процесса в системе. Первый параметр - указатель на процеду -обработчик, второй типа bool определяет, удаляется или добавляется обработчик.
				*/
				ntStatus = PsSetCreateProcessNotifyRoutine(ProcessCallback, FALSE);
				if (ntStatus != STATUS_SUCCESS)
				{
					return ntStatus;
				}
				//
				// Setup the global data structure
		
				g_ActivateInfo.bActivated = pActivateInfo->bActivated; 
			} // if
			else
			{
				//
				// restore the call back routine, thus givinig chance to the 
				// user mode application to unload dynamically the driver

				ntStatus = PsSetCreateProcessNotifyRoutine(ProcessCallback, TRUE);
				if (ntStatus != STATUS_SUCCESS)
					return ntStatus;
				else
					g_ActivateInfo.bActivated = FALSE;
			}
			ntStatus = STATUS_SUCCESS;
		} 
	} 
	return ntStatus;
}

//
// The dispatch routine

NTSTATUS DispatchIoctl(
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP           Irp
	)
{
    NTSTATUS               ntStatus = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION     irpStack  = IoGetCurrentIrpStackLocation(Irp);//получения указателя на стек IRP пакета используется функция:
    PDEVICE_EXTENSION      extension = DeviceObject->DeviceExtension;
    PPROCESS_CALLBACK_INFO pProcCallbackInfo;
	//
    // These IOCTL handlers are the set and get interfaces between
    // the driver and the user mode app

    switch(irpStack->Parameters.DeviceIoControl.IoControlCode)//получение управляющего IOCTL кода;
    {
		case IOCTL_PROCOBSRV_ACTIVATE_MONITORING:
			{
				ntStatus = ActivateMonitoringHanlder( Irp );
				break;
			}
        case IOCTL_PROCOBSRV_GET_PROCINFO:
			{
				if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >=// получение размера буфера которое ожидает приложение
				   sizeof(PROCESS_CALLBACK_INFO))
				{
					pProcCallbackInfo = Irp->AssociatedIrp.SystemBuffer;//получение переданного буфера
					pProcCallbackInfo->hParentId  = extension->hParentId;
					pProcCallbackInfo->hProcessId = extension->hProcessId;
					pProcCallbackInfo->bCreate    = extension->bCreate;
    
					ntStatus = STATUS_SUCCESS;
				}
				break;
			}

        default:
            break;
    }

    Irp->IoStatus.Status = ntStatus;
	//
    // Set number of bytes to copy back to user-mode

    if(ntStatus == STATUS_SUCCESS)
        Irp->IoStatus.Information = //количество переданных байт.
			irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    else
        Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return ntStatus;
}

//
// Driver unload routine

void UnloadDriver(
	IN PDRIVER_OBJECT DriverObject
	)
{
    UNICODE_STRING  uszDeviceString;
	//
	//  By default the I/O device is configured incorrectly or the 
	// configuration parameters to the driver are incorrect.

	NTSTATUS        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;

	if (g_ActivateInfo.bActivated)
		//
		// restore the call back routine, thus givinig chance to the 
		// user mode application to unload dynamically the driver

		ntStatus = PsSetCreateProcessNotifyRoutine(ProcessCallback, TRUE);

	IoDeleteDevice(DriverObject->DeviceObject);

	RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\ProcObsrv");
	IoDeleteSymbolicLink(&uszDeviceString);
}

//----------------------------End of the file -------------------------------
Соседние файлы в папке ProcObsrv
  • #
    15.06.20149.95 Кб58ProcObsrv.c
  • #
    15.06.20144.67 Кб58ProcObsrv.dsp
  • #
    15.06.20146.52 Кб58ProcObsrv.vcproj
  • #
    15.06.20141.4 Кб58ProcObsrv.vcproj.4-210-004.st210.user
  • #
    15.06.20141.4 Кб58ProcObsrv.vcproj.DREAMSLAVE.dreamslave.user
  • #
    15.06.20141.41 Кб58ProcObsrv.vcproj.MICROSOF-86932C.Admin.user