#include <ntddk.h>


#define IOCTL_RECV_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ALL_ACCESS)
#define IOCTL_START_MONITOR CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ALL_ACCESS)

UNICODE_STRING gDeviceName = RTL_CONSTANT_STRING(L"\\Device\\XXTEST");
UNICODE_STRING gSymbolicLink = RTL_CONSTANT_STRING(L"\\??\\XXEvent");
UNICODE_STRING EventName = RTL_CONSTANT_STRING(L"\\BaseNamedObjects\\XXTESTEVENT2");

PDEVICE_OBJECT gDeviceObject = NULL;
PKEVENT gEvent = { 0 };
PKEVENT localEvent = { 0 };
HANDLE hEvent = NULL;
KGUARDED_MUTEX gMutex = { 0 };


VOID XXoutine(PEPROCESS Process, HANDLE hProcessID, PPS_CREATE_NOTIFY_INFO Create)
{
	UNREFERENCED_PARAMETER(Process);
	UNREFERENCED_PARAMETER(hProcessID);
	UNREFERENCED_PARAMETER(Create);


	if (Create != NULL)
	{
		KeAcquireGuardedMutex(&gMutex);
		

		KeSetEvent(localEvent, 0, FALSE);
		KeClearEvent(localEvent);


		KeWaitForSingleObject(gEvent, Executive, UserMode, FALSE, NULL);
		/*KeClearEvent(gEvent);*/
		/*KeReleaseGuardedMutex(&gMutex);*/
		DbgPrint("%wZ", Create->ImageFileName);
		KeReleaseGuardedMutex(&gMutex);
	}



}


VOID Unload(PDRIVER_OBJECT DriverObject)
{
	UNREFERENCED_PARAMETER(DriverObject);

	IoDeleteSymbolicLink(&gSymbolicLink);
	IoDeleteDevice(gDeviceObject);
	PsSetCreateProcessNotifyRoutineEx(XXoutine, TRUE);
	ZwClose(hEvent);


	DbgPrint("Unloaded");
}



NTSTATUS IrpCreateClose(PDEVICE_OBJECT pDeviceObject, PIRP irp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);
	

	irp->IoStatus.Information = 0;
	irp->IoStatus.Status = STATUS_SUCCESS;

	IoCompleteRequest(irp, IO_NO_INCREMENT);
	

	return STATUS_SUCCESS;
}


VOID RegisterNotify(VOID)
{
	NTSTATUS status = STATUS_SUCCESS;
	status = PsSetCreateProcessNotifyRoutineEx(XXoutine, FALSE);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("Error create notify routine\n");
	}
}



NTSTATUS IoCtrl(PDEVICE_OBJECT pDeviceObject, PIRP Irp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);
	PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
	PVOID OutBuffer = Irp->AssociatedIrp.SystemBuffer;
	HANDLE hUserHandle = NULL;
	NTSTATUS status = STATUS_SUCCESS;

	if (irpsp->Parameters.DeviceIoControl.IoControlCode == IOCTL_RECV_EVENT)
	{
		
		hUserHandle = *(HANDLE*)OutBuffer;
		status = ObReferenceObjectByHandle(hUserHandle, SYNCHRONIZE, *ExEventObjectType, UserMode, &gEvent, NULL);
		if (!NT_SUCCESS(status))
		{
			DbgPrint("Error get usermode handle\n");
		}
		else {
			DbgPrint("Yeah i get usermode handle");
		}
	}

	if (irpsp->Parameters.DeviceIoControl.IoControlCode == IOCTL_START_MONITOR)
	{
		
		RegisterNotify();
		status = STATUS_SUCCESS;
	}






	Irp->IoStatus.Information = 0;
	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return status;
}







NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	UNREFERENCED_PARAMETER(RegistryPath);
	
	NTSTATUS status = STATUS_SUCCESS;


	DriverObject->DriverUnload = Unload;

	status = IoCreateDevice(DriverObject,
		0,
		&gDeviceName,
		FILE_DEVICE_UNKNOWN,
		FILE_DEVICE_SECURE_OPEN,
		FALSE,
		&gDeviceObject);

	if (!NT_SUCCESS(status))
	{
		DbgPrint("Error create DeviceDirectoryData object");
		return status;
	}

	status = IoCreateSymbolicLink(&gSymbolicLink, &gDeviceName);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("Error IoCreateSymbolicLink");
		IoDeleteDevice(gDeviceObject);
		return status;
	}


	DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] =  IrpCreateClose;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoCtrl;

	KeInitializeGuardedMutex(&gMutex);
	

	localEvent = IoCreateNotificationEvent(&EventName, &hEvent);
	KeClearEvent(localEvent);

	


	return status;
}