#include<Windows.h>
#include<wchar.h>
#include<stdarg.h> 

#define TEXT_SIZE  1000

void Help();
void Mem();
void Info();
BOOL Run(LPWSTR cmd);
BOOL PrintFormat(LPWSTR t, ...);
void PrintProcessNameAndID(DWORD processID);

BOOL Print(LPWSTR tekst)
{
	DWORD dw;
	return WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), tekst, lstrlen(tekst), &dw, NULL);
}

void PrintError(const LPWSTR text)
{
	MessageBox(NULL, text, L"Error", MB_OK);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{

	TCHAR tekst[TEXT_SIZE];

	if (!AllocConsole())
	{
		PrintError(L"AllocConsole error");
		return 1;
	}

	SetConsoleTitle(L"Konsola");

	Print(L"Type \"help\" for list of commands\n");

	DWORD dw;
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	TCHAR text[TEXT_SIZE];

	tekst[0] = L'\0';


	while (1)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
		Print(L"command >  ");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);

		if (!ReadConsole(GetStdHandle(STD_INPUT_HANDLE), text, TEXT_SIZE, &dw, NULL))
		{
			PrintError(L"ReadConsole error");
			break;
		}

		text[dw] = L'\0';

		TCHAR* tmp;
		TCHAR* cmd = wcstok_s(text, L"\r\n", &tmp);
		if (lstrlen(cmd) == 0) continue;

		if (lstrcmp(cmd, L"quit") == 0)
		{
			MessageBox(NULL, L"Good Bye!", L"Message", MB_OK);
			break;
		}

		if (lstrcmp(cmd, L"cls") == 0)
		{
			COORD cord0 = { 0, 0 };
			GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
			FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), L' ', csbi.dwSize.X * csbi.dwSize.Y, cord0, &dw);
			SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cord0);
			continue;
		}
	
		if (lstrcmp(cmd, L"help") == 0)
		{
			Help();
			continue;
		}
		if (lstrcmp(cmd, L"info") == 0)
		{
			Info();
			continue;
		}
		if (lstrcmp(cmd, L"mem") == 0)
		{
			Mem();
			continue;
		}
		Run(cmd);
	}

	FreeConsole();

	return 0;

}

void Help()
{
	Print(L"\nCommands:\n");
	Print(L"help           - this help\n");
	Print(L"cls            - clear screen\n");
	Print(L"info           - some system info\n");
	Print(L"mem            - global memory info\n");
	Print(L"quit           - exit console\n");
	Print(L"notepad        - runs notepad.exe\n");
	Print(L"\n");
}

void Mem()
{
	MEMORYSTATUSEX msx;
	msx.dwLength = sizeof(msx);
	GlobalMemoryStatusEx(&msx);
	TCHAR text[TEXT_SIZE];
	float div = 1024 * 1024;
	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Zajętośc pamięci: %d %%\n", msx.dwMemoryLoad);
	Print(text);
	
	Print(L"\nPamięć       |  dostępna | całkowita |\n");
	Print(L"--------------------------------------\n");
	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Fizyczna     | %5.1f MB | %5.1f MB |\n", (float)msx.ullAvailPhys / div, (float)msx.ullTotalPhys / div);
	Print(text);
	
	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Wirtualna    | %5.1f MB | %5.1f MB |\n", (float)msx.ullAvailVirtual / div, (float)msx.ullTotalVirtual / div );
	Print(text);

	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Stronicaowa  | %5.1f MB | %5.1f MB |\n", (float)msx.ullAvailPageFile / div, (float)msx.ullTotalPageFile / div);
	Print(text);
}

void Info()
{
	TCHAR text[TEXT_SIZE];

	SYSTEM_INFO siSysInfo;
	GetSystemInfo(&siSysInfo);
	
	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Ilość procesorów : %d\n", siSysInfo.dwNumberOfProcessors);
	Print(text);

	Print(L"Typ procesora    : ");
	switch (siSysInfo.wProcessorArchitecture)
	{
	case PROCESSOR_ARCHITECTURE_AMD64: Print(L"AMD 64\n"); break;
	case PROCESSOR_ARCHITECTURE_ARM: Print(L"ARM\n");  break;
	case PROCESSOR_ARCHITECTURE_IA64: Print(L"IA64\n"); break;
	case PROCESSOR_ARCHITECTURE_INTEL: Print(L"Intel\n"); 
	default:  Print(L"Nieznana\n"); break;
	}
	
	TCHAR bufor[MAX_COMPUTERNAME_LENGTH + 1];
	DWORD dw;
	GetComputerNameEx(ComputerNameDnsFullyQualified, bufor, &dw);

	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Nazwa DNS        : %s\n", bufor);
	Print(text);

	GetComputerNameEx(ComputerNameNetBIOS, bufor, &dw);
	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Nazwa NetBios    : %s\n", bufor);
	Print(text);

	int cx = GetSystemMetrics(SM_CXSCREEN);
	int cy = GetSystemMetrics(SM_CYSCREEN);

	_snwprintf_s(text, TEXT_SIZE, _TRUNCATE, L"Rozdzielczość    : %dx%d\n", cx, cy);
	Print(text);
}

BOOL Run(LPWSTR cmd)
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));

	// Start the child process. 
	if (!CreateProcess(NULL,   // No module name (use command line)
		cmd,        // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		0,              // No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory 
		&si,            // Pointer to STARTUPINFO structure
		&pi)           // Pointer to PROCESS_INFORMATION structure
		)
	{
		PrintFormat(L"Error: command %s failed\n", cmd);
		return false;
	}

	// Wait until child process exits.
	//WaitForSingleObject(pi.hProcess, INFINITE);
	PrintFormat( L"Command: %s\nProcess ID: %d\nThread ID: %d\n", cmd, pi.dwProcessId, pi.dwThreadId);

	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return true;
}


BOOL PrintFormat(LPWSTR t, ...)
{
	static TCHAR bufor[TEXT_SIZE];

	va_list vl;
	va_start(vl, t);
	_vsnwprintf_s(bufor, TEXT_SIZE, _TRUNCATE, t, vl);
	va_end(vl);
	return Print(bufor);
}


