<file_sep>#include "stdafx.h"
#include "DllProvider.h"


DllProvider::DllProvider()
{
	this->hDll = LoadLibrary(PATH);
	if (this->hDll == INVALID_HANDLE_VALUE)
	{
		this->isBad = true;
		return;
	}

	this->serialize = GetProcAddress(this->hDll, SERIALIZE);
	this->deserialize = GetProcAddress(this->hDll, DESERIALIZE);

	if (!this->serialize || !this->deserialize)
		this->isBad = true;
	this->Deserialize();
}

void DllProvider::ListEmptyMessage(void) const
{
	std::wcout << L"list of binds is empty!" << std::endl;
}

void DllProvider::InvalidIndex(void) const
{
	std::wcout << "Invalid index operation" << std::endl;
}

bool DllProvider::IsError(size_t index) const
{
	if (!this->pairs)
	{
		this->ListEmptyMessage();
		return false;
	}
	if (this->sizePairs >= index)
	{
		this->InvalidIndex();
		return false;
	}
	return true;
}

DllProvider* DllProvider::getInstance(void)
{
	if (!DllProvider::instance)
		DllProvider::instance = new DllProvider();

	return DllProvider::instance;
}

bool DllProvider::Serialize(void) const
{
	if (!this->pairs)
		return false;
	return reinterpret_cast
		<BOOL(*)(const PPAIR, DWORD)>
		(this->serialize)
		(this->pairs, this->sizePairs) == TRUE;
}

bool DllProvider::Deserialize(void)
{
	return reinterpret_cast
		<BOOL(*)(PPAIR, LPDWORD)>
		(this->deserialize)
		(this->pairs, (LPDWORD)&this->sizePairs) == TRUE;
}

void DllProvider::get(size_t id) const
{


	if (!this->IsError(id))
		return;
	std::wcout << L"LPARAM: " << std::endl;
	for (size_t i = 0; i < this->pairs[id].sizeArr; ++i)
		std::wcout << L"\t" << i << ": " <<
		this->pairs->arr[i] << std::endl;

	std::wcout << L"Is Caps: " << (bool)(this->pairs[id].isCaps) << std::endl;
	std::wcout << L"Is Shift: " << (bool)(this->pairs[id].isShift) << std::endl;
	std::wcout << L"Is Control: " << (bool)(this->pairs[id].isControl) << std::endl;
	std::wcout << L"Is Alt: " << (bool)(this->pairs[id].isAlt) << std::endl;

	std::wcout << L"Command: " << (this->pairs[id].strParams == nullptr ?
		L"Empty" : this->pairs[id].strParams) << std::endl;
}

void DllProvider::set(const LPARAM* pLparam, size_t cntParams, BOOL isCaps, BOOL isShift, BOOL isAlt, BOOL isControl, LPCWSTR strParam)
{
	if (this->sizePairs == 0)
		this->pairs = (PPAIR)calloc(1, sizeof(Pair));
	else
		this->pairs = (PPAIR)realloc(this->pairs, (this->sizePairs + 1) * sizeof(Pair));

	++this->sizePairs;

	for (size_t i = 0; i < this->sizePairs; ++i)
	{
		if (this->pairs[i].arr == nullptr)
			continue;
		if (this->pairs[i].arr[0] == pLparam[0] &&
			this->pairs[i].sizeArr == cntParams)
		{
			bool isCorrect = false;
			for (size_t j = 1; j < this->sizePairs; ++j)
			{
				if (this->pairs[i].arr[j] != pLparam[j])
				{
					isCorrect = true;
					break;
				}
			}
			if (!isCorrect)
			{
				std::wcout << L"Element already exists!" << std::endl;
				std::wcout << L"Try remove or edit element by index: " << i << std::endl;
				return;
			}
		}
	}
	Pair& p = this->pairs[this->sizePairs - 1];
	p.sizeArr = cntParams;
	p.arr = (LPARAM*)calloc(p.sizeArr, sizeof(LPARAM));
	memcpy_s(p.arr, p.sizeArr * sizeof(LPARAM), pLparam, cntParams * sizeof(LPARAM));
	p.isCaps = isCaps;
	p.isShift = isShift;
	p.isAlt = isAlt;
	p.isControl = isControl;
	p.strParams = (LPWSTR)calloc(wcslen(strParam) + 1, sizeof(WCHAR));
	memcpy_s(p.strParams, wcslen(strParam) * sizeof(wchar_t), strParam, wcslen(strParam) * sizeof(wchar_t));
	this->Serialize();
}

void DllProvider::edit(size_t id, LPCWSTR strParam)
{
	if (!this->IsError(id))
		return;
	if (strParam == nullptr ||
		!wcscmp(strParam, L""))
	{
		this->remove(id);
		return;
	}
	free(this->pairs[id].strParams);
	this->pairs[id].strParams = (LPWSTR)calloc(wcslen(strParam) + 1, sizeof(WCHAR));
	wcscpy_s(this->pairs[id].strParams, (wcslen(strParam) + 1), strParam);
}

void DllProvider::remove(size_t id)
{
	if (!this->IsError(id))
		return;
	free(this->pairs[id].arr);
	free(this->pairs[id].strParams);

	if (this->sizePairs == 1)
	{
		free(this->pairs);
		this->pairs = nullptr;
		return;
	}
	for (size_t i = id; i < this->sizePairs - 1; ++i)
		this->pairs[i] = this->pairs[i + 1];
	this->sizePairs -= 1;
	this->pairs = (PPAIR)realloc(this->pairs, this->sizePairs * sizeof(Pair));
}

void DllProvider::list(void) const
{
	if (this->sizePairs == 0)
	{
		this->ListEmptyMessage();
		return;
	}
	std::wcout << " id:\tButtons:\tCaps:\tShift:\tControl:\tAlt:\tCommand:" << std::endl;
	for (size_t i = 0; i < this->sizePairs; ++i)
	{
		std::wcout << ' ' << i << ' \t' << this->pairs[i].arr[0] << '\t'
			<< this->pairs[i].isCaps << '\t' << this->pairs[i].isControl
			<< '\t' << this->pairs[i].isAlt << '\t' << this->pairs[i].isAlt
			<< '\t' << this->pairs[i].strParams << std::endl;
		for (size_t j = 1; j < this->pairs[i].sizeArr; ++j)
			std::wcout << L"  \t" << this->pairs[i].arr[j];
	}
}

DllProvider::~DllProvider(void)
{
	if (!this->hDll ||
		this->hDll != INVALID_HANDLE_VALUE)
		FreeLibrary(this->hDll);
	if (this->pairs)
	{
		free(this->pairs);
		this->pairs = nullptr;
	}
}<file_sep>#include "stdafx.h"
#include "Parser.h"

void Parser::Get(void) const
{
	if (this->argc != 3)
	{
		std::wcout << L"Incorrect count of params!" << std::endl;
		std::wcout << L"\t-g <id> - get data by id" << std::endl;
		return;
	}

	size_t index = atoi(this->args[2]);
	if (index == 0 && this->args[2][0] != '0')
	{
		std::wcout << L"Incorrect value of index!" << std::endl;
		std::wcout << L"Index must be a numeric value" << std::endl;
		return;
	}
	DllProvider::getInstance()->get(index);
}

void Parser::Set(void) const
{

	if (this->argc < 8)
	{
		std::wcout << L"Error of count of params! This variant must have this params:" << std::endl;
		std::wcout << L"\t-s <id button> <isCaps> <isShift> <isControl> <isAlt> <command> - add\nbind" << std::endl;
		std::wcout << L"You can add more than one button. Separate codes by space" << std::endl;
		return;
	}
	size_t cntParams = this->argc - 7;
	std::auto_ptr<LPARAM> arr(new LPARAM[cntParams]);
	for (size_t i = 0; i < cntParams; ++i)
	{
		int id = atoi(this->args[2 + i]);
		if (id == 0 && this->args[2 + i][0] != '0')
		{
			std::wcout << L"Incorrect param of id button! Value must be integer!" << std::endl;
			return;
		}
		arr.get()[i] = (LPARAM)id;
	}

	std::auto_ptr<int> pArr(new int[1 << 2]);

	int(*pFn)(const char*) = [](const char* str) 
	{
		if (strlen(str) != 1)
			return -1;

		if (str[0] == '1' || str[0] == 't' || str[0] == 'y')
			return 1;
		if (str[0] == '0' || str[0] == 'f' || str[0] == 'n')
			return 0;

		return -1; 
	};
	for (size_t i = 0; i < 1 << 2; ++i)
	{
		pArr.get()[i] = pFn(this->args[this->argc - 5 + i]);
		if (pArr.get()[i] == -1)
		{
			std::wcout << L"Incorrect logical param!" << std::endl;
			std::wcout << L"Params must be 0, f or n - for false, 1, t or y - for true" << std::endl;
			return;
		}
	}
	if (!strlen(this->args[this->argc - 1]))
	{
		std::wcout << L"Empty string of params! Bind don't added" << std::endl;
		return;
	}

	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
	DllProvider::getInstance()->set(arr.get(),
		cntParams,
		pArr.get()[0],
		pArr.get()[1],
		pArr.get()[2],
		pArr.get()[3],
		(conv.from_bytes(this->args[this->argc - 1]).c_str()));
}

void Parser::Edit(void) const
{
	if (this->argc != 4)
	{
		std::wcout << L"Incorrect count of params!" << std::endl;
		std::wcout << L"\t-e <id> <command> - edit bind" << std::endl;
		return;
	}
	size_t index = atoi(this->args[2]);

	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
	std::wstring wstr = conv.from_bytes(this->args[3]);

	DllProvider::getInstance()->edit(index, wstr.data());
}

void Parser::Remove(void) const
{
	if (this->argc != 3)
	{
		std::wcout << L"Incorrect count of params!" << std::endl;
		std::wcout << L"\t-r <id> - remove bind by id" << std::endl;
		return;
	}

	size_t index = atoi(this->args[2]);
	if (index == 0 && this->args[2][0] != '0')
	{
		std::wcout << L"Incorrect value of index!" << std::endl;
		std::wcout << L"Index must be a numeric value" << std::endl;
		return;
	}
	DllProvider::getInstance()->remove(index);
}

void Parser::List(void)
{
	if (this->argc != 2)
	{
		std::wcout << L"This command must have only -l param" << std::endl;
		return;
	}
	DllProvider::getInstance()->list();
}
<file_sep>#pragma once
#include "DllProvider.h"
#include <locale>
#include <codecvt>
#include <string>
#include <memory>

class Parser
{
	int argc = 0;
	char** args = nullptr;

public:
	Parser() = delete;
	Parser(int argc, char** args) :
		argc(argc), args(args)
	{}

	Parser(const Parser&) = delete;
	Parser(Parser&&) = delete;
	Parser& operator =(const Parser&) = delete;
	Parser& operator =(Parser&&) = delete;
	~Parser() = default;

	void Get(void) const;
	void Set(void) const;
	void Edit(void) const;
	void Remove(void) const;
	void List(void);
};

<file_sep>// BindHandler.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include "Pair.h"
#include "DllProvider.h"
#include "Parser.h"
#include <string>

//g(get) id
//s(set) buttons, command
//e(edit) id, comand
//r(remove) id
//l(list)
//h, ?, help

DllProvider* DllProvider::instance = nullptr;

void Help(void);
void ShowError(void);
void ShowErrorLoadDLL(void);

int main(int argc, char** args)
{
	std::boolalpha(std::wcout);
	Parser p(argc, args);
	try
	{
		if (argc == 1)
		{
			Help();
			return 0;
		}

		if (DllProvider::getInstance()->bad())
		{
			ShowErrorLoadDLL();
			return 2;
		}

		std::string strParam(args[1]);
		if (strParam.length() != 2)
		{
			if (!strParam.compare("-help") ||
				!strParam.compare("/help"))
			{
				Help();
				return 0;
			}
			ShowError();
			return 1;
		}
		switch (strParam[1])
		{
		case '?':
		case 'h':
			Help();
			break;
		case 'g':
			p.Get();
			break;
		case 's':
			p.Set();
			break;
		case 'e':
			p.Edit();
			break;
		case 'r':
			p.Remove();
			break;
		case 'l':
			p.List();
			break;
		}
	}
	catch (const std::exception& ex)
	{
		std::cout << ex.what();
	}
	catch (...)
	{
		std::wcout << L"Unhandled exception" << std::endl;
	}
    return 0;
}

void Help(void)
{
	std::wcout << L"List of commands:" << std::endl;
	std::wcout << L"\t-g <id> - get data by id" << std::endl;
	std::wcout << L"\t-s <id button> <isCaps> <isShift> <isControl> <isAlt> <command> - add\nbind" << std::endl;
	std::wcout << L"\t-e <id> <command> - edit bind" << std::endl;
	std::wcout << L"\t-r <id> - remove bind by id" << std::endl;
	std::wcout << "\t-l - get list data" << std::endl;
	std::wcout << "\t-h, -?, -help - get help about programm" << std::endl;
	std::wcout << "\tBy VoidPtr (c)2018" << std::endl;
}

void ShowError(void)
{
	std::wcout << L"Incorrect param!" << std::endl;
	std::wcout << L"Use -h, -?, -help for help" << std::endl;
}

void ShowErrorLoadDLL(void)
{
	std::wcout << L"Error of load DLL!" << std::endl;
	std::wcout << L"Try reinstall programm" << std::endl;
}<file_sep>#pragma once
#include <Windows.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>

#define PATH L".\\combination.data"
#define EXPORT __declspec(dllexport)

typedef struct Pair
{
	LPDWORD arr; //arr iKey not LPARAM
	DWORD sizeArr;
	BOOL isCaps, isShift, isControl, isAlt;

	LPWSTR strParams;
} Pair;
typedef Pair* PPAIR;

typedef union ByteData
{
	INT32 val;
	BOOL arr[4];
} ByteData;

BOOL EXPORT Serialize(const PPAIR pairArr, DWORD size);
BOOL EXPORT Deserialize(PPAIR pairArr, LPDWORD size);
DWORD EXPORT IsFileEdit(PLARGE_INTEGER sizeFile);

BOOL EXPORT Serialize(const PPAIR pairArr, DWORD size)
{
//	HANDLE hFile = CreateFile(PATH,
//		GENERIC_WRITE,
//		FILE_SHARE_READ,
//		NULL,
//		CREATE_ALWAYS,
//		FILE_ATTRIBUTE_NORMAL,
//		NULL);
//	if (hFile == INVALID_HANDLE_VALUE)
//		return FALSE;
//
//	DWORD iCountWrited = 0;
//	if (!WriteFile(hFile, &size, sizeof(DWORD), &iCountWrited, NULL) &&
//		sizeof(DWORD) != iCountWrited)
//		goto err;
//	for (DWORD i = 0; i < size; ++i)
//	{
//		if (!WriteFile(hFile, &pairArr[i].sizeArr, sizeof(DWORD), &iCountWrited, NULL) &&
//			sizeof(DWORD) != iCountWrited)
//			goto err;
//		//if (!WriteFile(hFile, pairArr[i].arr, sizeof(DWORD)*pairArr[i].sizeArr, &iCountWrited, NULL))//
//			//goto err;
//		for (size_t j = 0; i < pairArr[i].sizeArr; ++j)
//		{
//			if (!WriteFile(hFile, &pairArr[i].arr[j], sizeof(DWORD), &iCountWrited, NULL) &&
//				sizeof(DWORD) != iCountWrited)
//				goto err;
//		}
//
//		ByteData bd = { 0 };
//		bd.arr[0] = pairArr[i].isCaps;
//		bd.arr[1] = pairArr[i].isShift;
//		bd.arr[2] = pairArr[i].isControl;
//		bd.arr[3] = pairArr[i].isAlt;
//		if (!WriteFile(hFile, &bd.val, sizeof(INT32), &iCountWrited, NULL) &&
//			sizeof(INT32) != iCountWrited)
//			goto err;
//		DWORD sizeStr = wcslen(pairArr[i].strParams);
//		if (!WriteFile(hFile, &sizeStr, sizeof(DWORD), &iCountWrited, NULL) && 
//			sizeof(DWORD) != iCountWrited)
//			goto err;
//		if (!WriteFile(hFile, pairArr[i].strParams, sizeStr * sizeof(WCHAR), &iCountWrited, NULL) &&
//			sizeStr * sizeof(WCHAR) != iCountWrited)
//			goto err;
//	}
//
//	CloseHandle(hFile);
//	return TRUE;
//err:
//	CloseHandle(hFile);
//	return FALSE;
	if (pairArr == NULL)
		return FALSE;
	if (size == 0)
		return TRUE;

	FILE* f = NULL;
	if (_wfopen_s(&f, PATH, L"w"))
		return FALSE;

	fwprintf(f, L"%d\n\n", size);
	for (size_t i = 0; i < size; ++i)
	{
		fwprintf(f, L"%d %d\n", pairArr[i].sizeArr, wcslen(pairArr[i].strParams));
		for (size_t j = 0; j < pairArr[i].sizeArr; ++j)
		{
			fwprintf(f, L"%d", pairArr[i].arr[j]);
			fwprintf(f, j == pairArr[i].sizeArr - 1 ? L"\n" : L" ");
		}
		fwprintf(f, L"%s\n", pairArr[i].strParams);
		fwprintf(f, L"%d %d %d %d\n\n",
			pairArr[i].isCaps,
			pairArr[i].isShift,
			pairArr[i].isControl,
			pairArr[i].isAlt);
	}

	fclose(f);
	return TRUE;
}
BOOL EXPORT Deserialize(PPAIR pairArr, LPDWORD size)
{
//	if (!size || !pairArr)
//	{
//		for (DWORD i = 0; i < *size; ++i)
//		{
//			free(pairArr[i].arr);
//			free(pairArr[i].strParams);
//		}
//		*size = 0;
//		free(pairArr);
//	}
//
//	HANDLE hFile = CreateFile(PATH,
//		GENERIC_READ,
//		FILE_SHARE_READ,
//		NULL,
//		OPEN_ALWAYS,
//		FILE_ATTRIBUTE_NORMAL,
//		NULL);
//	if (hFile == INVALID_HANDLE_VALUE)
//		return FALSE;
//
//	DWORD iCountReaded = 0;
//	if (!ReadFile(hFile, size, sizeof(DWORD), &iCountReaded, NULL) &&
//		sizeof(DWORD) != iCountReaded)
//		goto err;
//	pairArr = (PPAIR)calloc(*size, sizeof(Pair));
//	for (DWORD i = 0; i < *size; ++i)
//	{
//		if (!ReadFile(hFile, &pairArr[i].sizeArr, sizeof(DWORD), &iCountReaded, NULL) || iCountReaded != sizeof(DWORD))
//			goto err;
//		pairArr[i].arr = (LPDWORD)calloc(pairArr[i].sizeArr, sizeof(DWORD));
//		//if (!ReadFile(hFile, pairArr[i].arr, sizeof(DWORD) * pairArr[i].sizeArr, &iCountReaded, NULL) || iCountReaded != sizeof(DWORD) * pairArr[i].sizeArr)
//		//	goto err;
//		for (size_t j = 0; j < pairArr[i].sizeArr; ++j)
//		{
//			if (!ReadFile(hFile, &pairArr[i].arr[j], sizeof(DWORD), &iCountReaded, NULL) &&
//				sizeof(DWORD) != iCountReaded)
//				goto err;
//		}
//
//		ByteData bd = { 0 };
//		if (!ReadFile(hFile, &bd.val, sizeof(INT32), &iCountReaded, NULL) || iCountReaded != sizeof(INT32))
//			goto err;
//		pairArr[i].isCaps = bd.arr[0];
//		pairArr[i].isShift = bd.arr[1];
//		pairArr[i].isControl = bd.arr[2];
//		pairArr[i].isAlt = bd.arr[3];
//
//		DWORD sizeStr = 0;
//		if (!ReadFile(hFile, &sizeStr, sizeof(DWORD), &iCountReaded, NULL) || iCountReaded != sizeof(DWORD))
//			goto err;
//		pairArr[i].strParams = (LPWSTR)calloc(sizeStr + 1, sizeof(WCHAR));
//		if (!ReadFile(hFile, pairArr[i].strParams, sizeStr * sizeof(WCHAR), &iCountReaded, NULL) || iCountReaded != sizeStr * sizeof(WCHAR))
//			goto err;
//	}
//	CloseHandle(hFile);
//	return TRUE;
//err:
//	CloseHandle(hFile);
//	return FALSE;
	if (pairArr != NULL && *size != 0)
	{
		for (size_t i = 0; i < *size; ++i)
		{
			free(pairArr[i].arr);
			free(pairArr[i].strParams);
		}
		free(pairArr);
		*size = 0;
	}

	FILE* f = NULL;
	if (_wfopen_s(&f, PATH, L"r"))
		return FALSE;

	fwscanf_s(f, L"%d\n\n", size);
	pairArr = (PPAIR)calloc(*size, sizeof(Pair));
	for (size_t i = 0; i < *size; ++i)
	{
		DWORD sizeStr = 0;
		fwscanf_s(f, L"%d %d\n", &pairArr[i].sizeArr, &sizeStr);
		pairArr[i].arr = (LPDWORD)calloc(pairArr[i].sizeArr, sizeof(DWORD));
		pairArr[i].strParams = (LPWSTR)calloc(sizeStr + 1, sizeof(WCHAR));

		for (size_t j = 0; j < pairArr[i].sizeArr; ++j)
		{
			fwscanf_s(f, L"%d", &pairArr[i].arr[j]);
			fwscanf_s(f, j == pairArr[i].sizeArr - 1 ? L"\n" : L" ");
		}
		fgetws(pairArr[i].strParams, sizeStr, f);
		//fwscanf_s(f, L"%s\n", pairArr[i].strParams);
		int iArr[4] = { 0 };
		fwscanf_s(f, L"%d %d %d %d\n\n",
			&iArr[0],
			&iArr[1],
			&iArr[2],
			&iArr[3]);
		pairArr[i].isCaps = iArr[0] == 0 ? FALSE : TRUE;
		pairArr[i].isShift = iArr[1] == 0 ? FALSE : TRUE;
		pairArr[i].isControl = iArr[2] == 0 ? FALSE : TRUE;
		pairArr[i].isAlt = iArr[3] == 0 ? FALSE : TRUE;
	}

	fclose(f);
	return TRUE;
}

//Return val: 0 - good, 1 - value edit, 2 - error
DWORD EXPORT IsFileEdit(PLARGE_INTEGER sizeFile)
{
	LARGE_INTEGER tmp;
	HANDLE hFile = CreateFile(PATH,
		GENERIC_READ,
		FILE_SHARE_DELETE,
		NULL,
		OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 2;

	GetFileSizeEx(hFile, &tmp);
	DWORD result = tmp.QuadPart == sizeFile->QuadPart ? 0 : 1;
	if (result)
		sizeFile->QuadPart = tmp.QuadPart;
	CloseHandle(hFile);
	return result;
}<file_sep>#pragma once
#include "stdafx.h"
#include "Pair.h"

#define PATH L"FileSystemProvider.dll"
#define SERIALIZE "Serialize"
#define DESERIALIZE "Deserialize"
#define IS_FILE_EDIT "IsFileEdit"

class DllProvider
{
	HMODULE hDll = nullptr;
	FARPROC serialize = nullptr;
	FARPROC deserialize = nullptr;
	LARGE_INTEGER li = { 0 };
	PPAIR pairs = nullptr;
	size_t sizePairs = 0;
	bool isBad = false;

	DllProvider(void);
	static DllProvider* instance;

	void ListEmptyMessage(void) const;
	void InvalidIndex(void) const;
	bool IsError(size_t index) const;

public:

	static DllProvider* getInstance(void);

	bool Serialize(void) const;
	bool Deserialize(void);

	void get(size_t id) const;
	void set(const LPARAM* pLparam, size_t cntParams, BOOL isCaps, BOOL isShift, BOOL isAlt, BOOL isControl, LPCWSTR strParam);
	void edit(size_t id, LPCWSTR strParam);
	void remove(size_t id);
	void list(void) const;

	inline bool bad(void) const throw()
	{
		return this->isBad;
	}

	~DllProvider(void);
};

<file_sep>#pragma once
#include "stdafx.h"

typedef struct Pair
{
	LPARAM* arr;
	DWORD sizeArr;
	BOOL isCaps, isShift, isControl, isAlt;

	LPWSTR strParams;
} Pair;
typedef Pair* PPAIR;
