6
0
mirror of https://github.com/JKornev/hidden synced 2024-06-16 03:58:04 +00:00

/install and /uninstall commands

This commit is contained in:
JKornev 2016-12-23 03:05:09 +03:00
parent 93ea859610
commit 4f3e364d72
10 changed files with 394 additions and 33 deletions

@ -138,7 +138,7 @@ NTSTATUS CfgEnumConfigsTable(enum CfgMultiStringTables Table, CfgMultiStringCall
buffer = table->Buffer;
length = table->Length;
while (length > 0)
while (length > 1)
{
UNICODE_STRING entry;
ULONG inx, delta = 0;

@ -25,11 +25,88 @@ void LoadCommandsStack(vector<CommandPtr>& stack)
// =================
SingleCommand::SingleCommand(Arguments& args)
void ICommand::InstallCommand(RegistryKey& configKey)
{
throw WException(-2, L"Error, install mode is not supported");
}
void ICommand::UninstallCommand(RegistryKey& configKey)
{
}
// =================
CommandMode::CommandMode(Arguments& args) : m_type(CommandModeType::Execute)
{
wstring mode, all;
if (!args.Probe(mode))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
if (mode == L"/install")
{
args.SwitchToNext();
m_type = CommandModeType::Install;
LoadConfigPath(args);
}
else if (mode == L"/uninstall")
{
args.SwitchToNext();
m_type = CommandModeType::Uninstall;
LoadConfigPath(args);
}
if (m_type == CommandModeType::Uninstall)
{
if (!args.Probe(all) || all != L"all")
throw WException(-2, L"Error, invalid '/unistall' format");
args.SwitchToNext();
}
}
void CommandMode::LoadConfigPath(Arguments& args)
{
wstring path;
if (!args.Probe(path) || path.compare(0, 1, L"/") == 0 || path == L"all")
{
m_regConfigPath = L"System\\CurrentControlSet\\Services\\Hidden";
return;
}
args.SwitchToNext();
m_regConfigPath = L"System\\CurrentControlSet\\Services\\";
m_regConfigPath += path;
}
CommandModeType CommandMode::GetModeType()
{
return m_type;
}
const wstring& CommandMode::GetConfigRegistryKeyPath()
{
return m_regConfigPath;
}
// =================
SingleCommand::SingleCommand(Arguments& args, CommandModeType mode)
{
wstring arg;
bool found = false;
if (mode == CommandModeType::Uninstall)
{
if (args.SwitchToNext())
throw WException(-2, L"Error, too many arguments");
LoadCommandsStack(m_commandsStack);
return;
}
if (!args.GetNext(arg))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
@ -62,12 +139,26 @@ void SingleCommand::Perform(Connection& connection)
m_current->PerformCommand(connection);
}
void SingleCommand::Install(RegistryKey& configKey)
{
m_current->InstallCommand(configKey);
}
void SingleCommand::Uninstall(RegistryKey& configKey)
{
for (auto it = m_commandsStack.begin(); it != m_commandsStack.end(); it++)
(*it)->UninstallCommand(configKey);
}
// =================
MultipleCommands::MultipleCommands(Arguments& args)
MultipleCommands::MultipleCommands(Arguments& args, CommandModeType mode)
{
wstring arg;
if (mode == CommandModeType::Uninstall)
throw WException(-2, L"Error, /uninstall can't be combined with /multi");
if (!args.GetNext(arg))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
@ -105,6 +196,17 @@ void MultipleCommands::Perform(Connection& connection)
(*it)->PerformCommand(connection);
}
void MultipleCommands::Install(RegistryKey& configKey)
{
for (auto it = m_currentStack.begin(); it != m_currentStack.end(); it++)
(*it)->InstallCommand(configKey);
}
void MultipleCommands::Uninstall(RegistryKey& configKey)
{
throw WException(-2, L"Error, uninstall mode is not supported");
}
// =================
class ArgsParser
@ -157,22 +259,25 @@ public:
};
MultipleCommandsFromFile::MultipleCommandsFromFile(Arguments& args)
MultipleCommandsFromFile::MultipleCommandsFromFile(Arguments& args, CommandModeType mode)
{
wstring configFile;
if (mode == CommandModeType::Uninstall)
throw WException(-2, L"Error, /uninstall can't be combined with /config");
if (!args.GetNext(configFile))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
if (args.SwitchToNext())
throw WException(-2, L"Error, too many arguments");
wifstream config(configFile);
wifstream fconfig(configFile);
wstring line;
LoadCommandsStack(m_commandsStack);
while (getline(config, line))
while (getline(fconfig, line))
{
ArgsParser parser(line);
wstring arg;
@ -218,3 +323,13 @@ void MultipleCommandsFromFile::Perform(Connection& connection)
(*it)->PerformCommand(connection);
}
void MultipleCommandsFromFile::Install(RegistryKey& configKey)
{
for (auto it = m_currentStack.begin(); it != m_currentStack.end(); it++)
(*it)->InstallCommand(configKey);
}
void MultipleCommandsFromFile::Uninstall(RegistryKey& configKey)
{
throw WException(-2, L"Error, uninstall mode is not supported");
}

@ -14,56 +14,86 @@ public:
virtual bool CompareCommand(std::wstring& command) = 0;
virtual void LoadArgs(Arguments& args) = 0;
virtual void PerformCommand(Connection& connection) = 0;
virtual void InstallCommand(RegistryKey& configKey);
virtual void UninstallCommand(RegistryKey& configKey);
virtual CommandPtrInternal CreateInstance() = 0;
};
typedef ICommand::CommandPtrInternal CommandPtr;
class ICommandMode
{
public:
virtual ~ICommandMode() {}
virtual void Perform(Connection& connection) = 0;
enum CommandModeType {
Execute,
Install,
Uninstall
};
typedef std::shared_ptr<ICommandMode> CommandModePtr;
class CommandMode
{
std::wstring m_regConfigPath;
CommandModeType m_type;
class SingleCommand : public ICommandMode
void LoadConfigPath(Arguments& args);
public:
CommandMode(Arguments& args);
CommandModeType GetModeType();
const std::wstring& GetConfigRegistryKeyPath();
};
class ICommandTemplate
{
public:
virtual ~ICommandTemplate() {}
virtual void Perform(Connection& connection) = 0;
virtual void Install(RegistryKey& configKey) = 0;
virtual void Uninstall(RegistryKey& configKey) = 0;
};
typedef std::shared_ptr<ICommandTemplate> CommandTemplatePtr;
class SingleCommand : public ICommandTemplate
{
std::vector<CommandPtr> m_commandsStack;
CommandPtr m_current;
public:
SingleCommand(Arguments& args);
SingleCommand(Arguments& args, CommandModeType mode);
virtual ~SingleCommand();
virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
};
class MultipleCommands : public ICommandMode
class MultipleCommands : public ICommandTemplate
{
std::vector<CommandPtr> m_commandsStack;
std::vector<CommandPtr> m_currentStack;
public:
MultipleCommands(Arguments& args);
MultipleCommands(Arguments& args, CommandModeType mode);
virtual ~MultipleCommands();
virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
};
class MultipleCommandsFromFile : public ICommandMode
class MultipleCommandsFromFile : public ICommandTemplate
{
std::vector<CommandPtr> m_commandsStack;
std::vector<CommandPtr> m_currentStack;
public:
MultipleCommandsFromFile(Arguments& args);
MultipleCommandsFromFile(Arguments& args, CommandModeType mode);
virtual ~MultipleCommandsFromFile();
virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
};

@ -1,7 +1,10 @@
#include "helper.h"
#include <memory>
using namespace std;
// =================
WException::WException(unsigned int Code, wchar_t* Format, ...) :
m_errorCode(Code)
{
@ -25,6 +28,8 @@ unsigned int WException::Code()
return m_errorCode;
}
// =================
Arguments::Arguments(int argc, wchar_t* argv[], int start) :
m_argPointer(0)
{
@ -64,6 +69,8 @@ bool Arguments::GetNext(wstring& arg)
return true;
}
// =================
Handle::Handle(HANDLE handle) :
m_handle(handle),
m_error(::GetLastError())
@ -86,6 +93,146 @@ DWORD Handle::Error()
return m_error;
}
// =================
RegistryKey::RegistryKey(std::wstring regKey) : m_hkey(NULL)
{
LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, regKey.c_str(), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &m_hkey);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't open registry key");
}
RegistryKey::~RegistryKey()
{
RegCloseKey(m_hkey);
}
void RegistryKey::SetDwordValue(const wchar_t* name, DWORD value)
{
LONG status;
status = RegSetValueExW(m_hkey, name, NULL, REG_DWORD, (LPBYTE)&value, sizeof(value));
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
}
DWORD RegistryKey::GetDwordValue(const wchar_t* name, DWORD defValue)
{
DWORD value, size = sizeof(value), type = REG_DWORD;
LONG status;
status = RegQueryValueEx(m_hkey, name, NULL, &type, (LPBYTE)&value, &size);
if (status != ERROR_SUCCESS)
{
if (status != ERROR_FILE_NOT_FOUND)
throw WException(status, L"Error, can't query registry value");
return defValue;
}
return value;
}
void RegistryKey::SetMultiStrValue(const wchar_t* name, const std::vector<std::wstring>& strs)
{
DWORD size = 0, offset = 0;
shared_ptr<BYTE> buffer;
LONG status;
for (auto it = strs.begin(); it != strs.end(); it++)
{
if (it->size() > 0)
size += (it->size() + 1) * sizeof(wchar_t);
}
if (size == 0)
{
WCHAR value = 0;
status = RegSetValueExW(m_hkey, name, NULL, REG_MULTI_SZ, (LPBYTE)&value, 2);
if(status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
return;
}
buffer.reset(new BYTE[size]);
memset(buffer.get(), 0, size);
for (auto it = strs.begin(); it != strs.end(); it++)
{
if (it->size() == 0)
continue;
DWORD strSize = (it->size() + 1) * sizeof(wchar_t);
memcpy(buffer.get() + offset, it->c_str(), strSize);
offset += strSize;
}
status = RegSetValueExW(m_hkey, name, NULL, REG_MULTI_SZ, buffer.get(), size);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
}
void RegistryKey::GetMultiStrValue(const wchar_t* name, std::vector<std::wstring>& strs)
{
DWORD size = 0, type = REG_MULTI_SZ;
shared_ptr<BYTE> buffer;
LPWSTR bufferPtr;
LONG status;
strs.clear();
status = RegQueryValueEx(m_hkey, name, NULL, &type, NULL, &size);
if (status != ERROR_SUCCESS)
{
if (status != ERROR_FILE_NOT_FOUND)
throw WException(status, L"Error, can't query registry value");
return;
}
if (size == 0)
return;
buffer.reset(new BYTE[size + sizeof(WCHAR)]);
memset(buffer.get(), 0, size + sizeof(WCHAR));
status = RegQueryValueEx(m_hkey, name, NULL, &type, buffer.get(), &size);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't query registry value");
bufferPtr = (LPWSTR)buffer.get();
while (size > 1)
{
ULONG inx, delta = 0;
ULONG len = size / sizeof(WCHAR);
for (inx = 0; inx < len; inx++)
{
if (bufferPtr[inx] == L'\0')
{
delta = 1;
break;
}
}
if (inx > 0)
strs.push_back(bufferPtr);
size -= (inx + delta) * sizeof(WCHAR);
bufferPtr += (inx + delta);
}
}
void RegistryKey::RemoveValue(const wchar_t* name)
{
LONG status = RegDeleteKeyValue(m_hkey, NULL, name);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't delete registry value");
}
// =================
HidRegRootTypes GetRegType(wstring& path)
{
static wchar_t regHKLM[] = L"HKLM\\";

@ -53,6 +53,26 @@ public:
};
class RegistryKey
{
private:
HKEY m_hkey;
public:
RegistryKey(std::wstring regKey);
~RegistryKey();
void SetDwordValue(const wchar_t* name, DWORD value);
DWORD GetDwordValue(const wchar_t* name, DWORD defValue);
void SetMultiStrValue(const wchar_t* name, const std::vector<std::wstring>& strs);
void GetMultiStrValue(const wchar_t* name, std::vector<std::wstring>& strs);
void RemoveValue(const wchar_t* name);
};
enum EObjTypes {
TypeFile,
TypeDir,

@ -32,6 +32,10 @@ bool PrintUsage(Arguments& args)
L" parameter is used for set valid registry path if driver name is changed, by\n"
L" default \"hidden\"\n"
L"\n"
L" /uninstall [%driver%] all\n"
L" Uninstall all configs from registry. This flag is all-sufficient therefore\n"
L" if this flag is set no other parameters and commands should be set after\n"
L"\n"
L"connection:\n"
L"\n"
L" /gate <%name%>\n"
@ -45,7 +49,7 @@ bool PrintUsage(Arguments& args)
L" Enable multiple commands per execution, just type commands one by one\n"
L" without any separator\n"
L"\n"
L" /config\n"
L" /config <%path%>\n"
L" Loads multiple commands from file, each command should be on separate line\n"
L"\n"
L"commands:\n"
@ -107,25 +111,28 @@ bool PrintUsage(Arguments& args)
return true;
}
CommandModePtr LoadCommands(Arguments& args)
CommandTemplatePtr LoadCommandsTemplate(Arguments& args, CommandMode& mode)
{
wstring command;
wstring templateType;
if (!args.Probe(command))
throw WException(-2, L"Error, unknown mode, please use 'hiddencli /help'");
if (mode.GetModeType() == CommandModeType::Uninstall)
return CommandTemplatePtr(new SingleCommand(args, mode.GetModeType()));
if (command == L"/multi")
if (!args.Probe(templateType))
throw WException(-2, L"Error, unknown perform mode, please use 'hiddencli /help'");
if (templateType == L"/multi")
{
args.SwitchToNext();
return CommandModePtr(new MultipleCommands(args));
return CommandTemplatePtr(new MultipleCommands(args, mode.GetModeType()));
}
else if (command == L"/config")
else if (templateType == L"/config")
{
args.SwitchToNext();
return CommandModePtr(new MultipleCommandsFromFile(args));
return CommandTemplatePtr(new MultipleCommandsFromFile(args, mode.GetModeType()));
}
return CommandModePtr(new SingleCommand(args));
return CommandTemplatePtr(new SingleCommand(args, mode.GetModeType()));
}
int wmain(int argc, wchar_t* argv[])
@ -146,9 +153,24 @@ int wmain(int argc, wchar_t* argv[])
return 0;
{
CommandModePtr commands = LoadCommands(arguments);
connection.Open();
commands->Perform(connection);
CommandMode mode(arguments);
CommandTemplatePtr commands = LoadCommandsTemplate(arguments, mode);
if (mode.GetModeType() == CommandModeType::Execute)
{
connection.Open();
commands->Perform(connection);
}
else if (mode.GetModeType() == CommandModeType::Install)
{
RegistryKey key(mode.GetConfigRegistryKeyPath());
commands->Install(key);
}
else if (mode.GetModeType() == CommandModeType::Uninstall)
{
RegistryKey key(mode.GetConfigRegistryKeyPath());
commands->Uninstall(key);
}
}
}
catch (WException& exception)

@ -43,6 +43,20 @@ void CommandState::PerformCommand(Connection& connection)
wcout << L"status:ok" << endl;
}
void CommandState::InstallCommand(RegistryKey& configKey)
{
configKey.SetDwordValue(L"Hid_State", (m_state ? 1 : 0));
wcerr << L"Install 'state' successful" << endl;
wcout << L"status:ok" << endl;
}
void CommandState::UninstallCommand(RegistryKey& configKey)
{
configKey.RemoveValue(L"Hid_State");
wcerr << L"Uninstall 'state' successful" << endl;
wcout << L"status:ok" << endl;
}
CommandPtr CommandState::CreateInstance()
{
return CommandPtr(new CommandState());

@ -16,6 +16,8 @@ public:
virtual bool CompareCommand(std::wstring& command);
virtual void LoadArgs(Arguments& args);
virtual void PerformCommand(Connection& connection);
virtual void InstallCommand(RegistryKey& configKey);
virtual void UninstallCommand(RegistryKey& configKey);
virtual CommandPtr CreateInstance();
};

@ -11,10 +11,14 @@ mode:
connection parameters shouldn't be set. Optional parameter is used for set valid registry path if
driver name is changed, by default "hidden"
/uninstall [%driver%]
Uninstall all configs from registry. This flag is all-sufficient therefore if this flag is set
no other parameters and commands should be set after
connection:
/gate <%name%>
Set specific connection gate name (driver device name)
Set specific connection gate name (driver device name)
perform:
@ -23,7 +27,7 @@ perform:
/multi
Enable multiple commands per execution, just type commands one by one without any separator
/config
/config <%path%>
Loads multiple commands from file, each command should be on separate line
commands:

@ -5,6 +5,13 @@
; Enable driver if it's disabled
/state on
; Cleanup configs
/unhide file all
/unhide dir all
/unhide regval all
/unhide regkey all
; Following config used for hidding VMWare components
/hide dir "c:\Program Files\VMware"