159 lines
5.2 KiB
C++
159 lines
5.2 KiB
C++
|
#include <sstream>
|
||
|
|
||
|
#include "util.h"
|
||
|
#include "config.h"
|
||
|
#include "logger.h"
|
||
|
#include "base64.h"
|
||
|
#include "file.h"
|
||
|
#include <cstring>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
#ifdef WIN32
|
||
|
bool is_executable(const std::string& file) {
|
||
|
DWORD lpBinaryType[100];
|
||
|
return GetBinaryTypeA(file.c_str(), lpBinaryType);
|
||
|
}
|
||
|
|
||
|
VOID execute_app(LPCTSTR lpApplicationName,LPSTR arguments)
|
||
|
{
|
||
|
// additional information
|
||
|
STARTUPINFO si;
|
||
|
PROCESS_INFORMATION pi;
|
||
|
|
||
|
// set the size of the structures
|
||
|
ZeroMemory( &si, sizeof(si) );
|
||
|
si.cb = sizeof(si);
|
||
|
ZeroMemory( &pi, sizeof(pi) );
|
||
|
|
||
|
// start the program up
|
||
|
auto result = CreateProcess( lpApplicationName, // the path
|
||
|
arguments, // Command line
|
||
|
nullptr, // Process handle not inheritable
|
||
|
nullptr, // Thread handle not inheritable
|
||
|
FALSE, // Set handle inheritance to FALSE
|
||
|
CREATE_NEW_CONSOLE , // No creation flags
|
||
|
nullptr, // Use parent's environment block
|
||
|
nullptr, // Use parent's starting directory
|
||
|
&si, // Pointer to STARTUPINFO structure
|
||
|
&pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
|
||
|
);
|
||
|
// Close process and thread handles.
|
||
|
CloseHandle( pi.hProcess );
|
||
|
CloseHandle( pi.hThread );
|
||
|
}
|
||
|
#else
|
||
|
#include <unistd.h>
|
||
|
bool is_executable(const std::string& file) {
|
||
|
return access(file.c_str(), F_OK | X_OK) == 0;
|
||
|
}
|
||
|
|
||
|
typedef const char* LPSTR;
|
||
|
typedef const char* LPCTSTR;
|
||
|
|
||
|
void execute_app(LPCTSTR, LPSTR app_arguments) {
|
||
|
auto arguments_length = strlen(app_arguments);
|
||
|
|
||
|
auto buffer_size = arguments_length + 512;
|
||
|
auto buffer = (char*) malloc(buffer_size);
|
||
|
|
||
|
memcpy(buffer, app_arguments, arguments_length);
|
||
|
memcpy(buffer + arguments_length, " &", 2);
|
||
|
|
||
|
system(app_arguments);
|
||
|
free(buffer);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
extern std::string log_file_path;
|
||
|
inline std::string build_callback_info(const std::string& error_id, const std::string& error_message) {
|
||
|
stringstream ss;
|
||
|
|
||
|
ss << ";log_file:" << base64::encode(log_file_path);
|
||
|
if(!error_id.empty()) {
|
||
|
ss << ";error_id:" << base64::encode(error_id);
|
||
|
ss << ";error_message:" << base64::encode(error_message);
|
||
|
}
|
||
|
auto result = ss.str();
|
||
|
if(result.length() > 0)
|
||
|
result = result.substr(1);
|
||
|
return base64::encode(result);
|
||
|
}
|
||
|
|
||
|
void execute_callback_fail_exit(const std::string& error, const std::string& error_message) {
|
||
|
if(!is_executable(config::callback_file)) {
|
||
|
logger::fatal("callback file (%s) is not executable! Ignoring fail callback", config::callback_file.c_str());
|
||
|
logger::flush();
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
file::rollback();
|
||
|
auto cmd_line = config::callback_file + " " + config::callback_argument_fail + build_callback_info(error, error_message);
|
||
|
logger::info("executing callback file %s with fail command line %s", config::callback_file.c_str(), cmd_line.c_str());
|
||
|
logger::flush();
|
||
|
execute_app((LPCTSTR) config::callback_file.c_str(), (LPSTR) cmd_line.c_str());
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
void execute_callback_success_exit() {
|
||
|
if(!is_executable(config::callback_file)) {
|
||
|
logger::fatal("callback file (%s) is not executable! Ignoring success callback", config::callback_file.c_str());
|
||
|
logger::flush();
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
auto cmd_line = config::callback_file + " " + config::callback_argument_success + build_callback_info("", "");
|
||
|
logger::info("executing callback file %s with success with command line %s", config::callback_file.c_str(), cmd_line.c_str());
|
||
|
logger::flush();
|
||
|
execute_app((LPCTSTR) config::callback_file.c_str(), (LPSTR) cmd_line.c_str());
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
bool is_administrator() {
|
||
|
BOOL result = false;
|
||
|
DWORD error = ERROR_SUCCESS;
|
||
|
PSID admin_groups = nullptr;
|
||
|
|
||
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
if (!AllocateAndInitializeSid(
|
||
|
&NtAuthority,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0, 0, 0, 0, 0, 0,
|
||
|
&admin_groups)) {
|
||
|
error = GetLastError();
|
||
|
}
|
||
|
|
||
|
if (error == ERROR_SUCCESS && !CheckTokenMembership(nullptr, admin_groups, &result))
|
||
|
error = GetLastError();
|
||
|
|
||
|
if (admin_groups) {
|
||
|
FreeSid(admin_groups);
|
||
|
admin_groups = nullptr;
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS != error && result;
|
||
|
}
|
||
|
|
||
|
extern bool request_administrator() {
|
||
|
if(!is_administrator()) {
|
||
|
char szPath[MAX_PATH];
|
||
|
if (GetModuleFileName(nullptr, szPath, ARRAYSIZE(szPath))) {
|
||
|
SHELLEXECUTEINFO sei = { sizeof(sei) };
|
||
|
|
||
|
sei.lpVerb = "runas";
|
||
|
sei.lpFile = szPath;
|
||
|
sei.hwnd = nullptr;
|
||
|
sei.nShow = SW_NORMAL;
|
||
|
|
||
|
if (!ShellExecuteEx(&sei)) {
|
||
|
if (GetLastError() == ERROR_CANCELLED)
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
#endif
|