From 190ff781eaee33e7a61aab44fc4133718cc0515b Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sat, 13 Jun 2026 00:36:59 +0200 Subject: add .clang-format --- .clang-format | 28 +++++ src/cmd_line.hpp | 74 +++++-------- src/error.hpp | 41 ++++--- src/handle.hpp | 45 +++----- src/main.cpp | 319 +++++++++++++++++++++++-------------------------------- src/os.hpp | 44 ++++---- src/process.cpp | 88 +++++++-------- src/process.hpp | 46 ++++---- src/resource.hpp | 25 ++--- src/sid.cpp | 94 ++++++++-------- src/sid.hpp | 15 +-- src/string.hpp | 229 ++++++++++++++++++--------------------- src/token.cpp | 229 +++++++++++++++++++-------------------- src/token.hpp | 48 +++++---- 14 files changed, 612 insertions(+), 713 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..27d7ce1 --- /dev/null +++ b/.clang-format @@ -0,0 +1,28 @@ +--- +Language: Cpp +BasedOnStyle: Chromium + +IndentWidth: 4 + +AccessModifierOffset: -4 +AlignConsecutiveMacros: AcrossComments +AllowShortFunctionsOnASingleLine: Empty +BinPackArguments: false +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: false +ColumnLimit: 100 +IncludeBlocks: Regroup +SpacesBeforeTrailingComments: 1 +WrapNamespaceBodyWithEmptyLines: Always + +IncludeCategories: + - Regex: '^".+' + Priority: 1 + - Regex: '^$' + Priority: 3 + - Regex: '.*' + Priority: 4 +... diff --git a/src/cmd_line.hpp b/src/cmd_line.hpp index ae96ed5..b1eb2a5 100644 --- a/src/cmd_line.hpp +++ b/src/cmd_line.hpp @@ -8,28 +8,26 @@ #include "error.hpp" #include "string.hpp" +/* clang-format off */ #include #include +/* clang-format on */ #include - #include -#include #include +#include #include #include #include -class CommandLine -{ +class CommandLine { public: - static CommandLine query() - { + static CommandLine query() { return build_from_string(GetCommandLine()); } - static CommandLine build_from_main(int argc, wchar_t* argv[]) - { + static CommandLine build_from_main(int argc, wchar_t* argv[]) { if (argc < 1) throw std::range_error{"invalid argc value"}; @@ -48,33 +46,27 @@ public: CommandLine() = default; - bool has_argv0() const - { + bool has_argv0() const { return !argv0.empty(); } - std::wstring get_argv0() const - { + std::wstring get_argv0() const { return argv0; } - std::wstring escape_argv0() const - { + std::wstring escape_argv0() const { return escape(get_argv0()); } - bool has_args() const - { + bool has_args() const { return !get_args().empty(); } - const std::vector& get_args() const - { + const std::vector& get_args() const { return args; } - std::vector escape_args() const - { + std::vector escape_args() const { std::vector safe; safe.reserve(args.size()); for (const auto& arg : args) @@ -82,15 +74,15 @@ public: return safe; } - static constexpr wchar_t sep() { return L' '; } + static constexpr wchar_t sep() { + return L' '; + } - std::wstring join_args() const - { + std::wstring join_args() const { return string::join(sep(), escape_args()); } - std::wstring join() const - { + std::wstring join() const { if (!has_argv0()) throw std::logic_error{"argv[0] isn't defined"}; std::wostringstream oss; @@ -101,8 +93,7 @@ public: } private: - static CommandLine build_from_string(std::wstring src) - { + static CommandLine build_from_string(std::wstring src) { string::trim(src); if (src.empty()) return {}; @@ -127,8 +118,7 @@ private: return {std::move(argv0), std::move(args)}; } - inline std::wstring escape_for_cmd(const std::wstring& arg) - { + inline std::wstring escape_for_cmd(const std::wstring& arg) { static constexpr auto escape_symbol = L'^'; static constexpr auto dangerous_symbols = L"!\"%&()<>^|"; @@ -137,29 +127,25 @@ private: return safe; } - static std::wstring escape(const std::wstring& arg) - { + static std::wstring escape(const std::wstring& arg) { std::wstring safe; safe.reserve(arg.length() + 2); safe.push_back(L'"'); - for (auto it = arg.cbegin(); it != arg.cend(); ++it) - { + for (auto it = arg.cbegin(); it != arg.cend(); ++it) { std::size_t numof_backslashes = 0; for (; it != arg.cend() && *it == L'\\'; ++it) ++numof_backslashes; - if (it == arg.cend()) - { + if (it == arg.cend()) { safe.reserve(safe.capacity() + numof_backslashes); safe.append(2 * numof_backslashes, L'\\'); break; } - switch (*it) - { + switch (*it) { case L'"': safe.reserve(safe.capacity() + numof_backslashes + 1); safe.append(2 * numof_backslashes + 1, L'\\'); @@ -177,22 +163,16 @@ private: return safe; } - struct LocalDelete - { - void operator()(wchar_t* argv[]) const - { + struct LocalDelete { + void operator()(wchar_t* argv[]) const { LocalFree(argv); } }; - CommandLine(std::vector&& args) - : args{std::move(args)} - { } + CommandLine(std::vector&& args) : args{std::move(args)} {} CommandLine(std::wstring&& argv0, std::vector&& args = {}) - : argv0{std::move(argv0)} - , args{std::move(args)} - { } + : argv0{std::move(argv0)}, args{std::move(args)} {} const std::wstring argv0; const std::vector args; diff --git a/src/error.hpp b/src/error.hpp index 04ec8c9..8a0778c 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -12,26 +12,23 @@ typedef std::system_error Error; -namespace error -{ - inline Error make(const char* function_name) - { - const auto ec = GetLastError(); - return {static_cast(ec), std::system_category(), function_name}; - } - - inline void raise(const char* function_name) - { - throw make(function_name); - } - - inline void report(const std::exception& e) - { - MessageBoxA(NULL, e.what(), NULL, MB_OK); - } - - inline int get_code(const Error& e) - { - return e.code().value(); - } +namespace error { + +inline Error make(const char* function_name) { + const auto ec = GetLastError(); + return {static_cast(ec), std::system_category(), function_name}; +} + +inline void raise(const char* function_name) { + throw make(function_name); +} + +inline void report(const std::exception& e) { + MessageBoxA(NULL, e.what(), NULL, MB_OK); +} + +inline int get_code(const Error& e) { + return e.code().value(); } + +} // namespace error diff --git a/src/handle.hpp b/src/handle.hpp index 4bc0a97..5839594 100644 --- a/src/handle.hpp +++ b/src/handle.hpp @@ -8,51 +8,41 @@ #include #include - #include #include -class Handle -{ +class Handle { public: Handle() = default; - explicit Handle(HANDLE raw) - : impl{raw} - { } + explicit Handle(HANDLE raw) : impl{raw} {} - Handle(Handle&& other) noexcept - { + Handle(Handle&& other) noexcept { swap(other); } - Handle& operator=(Handle other) noexcept - { + Handle& operator=(Handle other) noexcept { swap(other); return *this; } - void swap(Handle& other) noexcept - { + void swap(Handle& other) noexcept { using std::swap; swap(impl, other.impl); } - operator HANDLE() const - { + operator HANDLE() const { return impl.get(); } private: - struct Close - { - void operator()(HANDLE raw) const - { + struct Close { + void operator()(HANDLE raw) const { if (raw == NULL || raw == INVALID_HANDLE_VALUE) return; const auto ret = CloseHandle(raw); assert(ret); - (void) ret; + (void)ret; } }; @@ -61,16 +51,15 @@ private: Handle(const Handle&) = delete; }; -inline void swap(Handle& a, Handle& b) noexcept -{ +inline void swap(Handle& a, Handle& b) noexcept { a.swap(b); } -namespace std -{ - template <> - inline void swap(Handle& a, Handle& b) noexcept - { - a.swap(b); - } +namespace std { + +template <> +inline void swap(Handle& a, Handle& b) noexcept { + a.swap(b); } + +} // namespace std diff --git a/src/main.cpp b/src/main.cpp index 4065a5e..8b81587 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,242 +11,189 @@ #include "sid.hpp" #include "token.hpp" -#include +/* clang-format off */ #include +#include #include +/* clang-format on */ #include #include #if defined(_MSC_VER) -#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#pragma comment( \ + linker, \ + "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #endif -namespace -{ - HWND get_dialog_item(HWND wnd, int id) - { - const auto lbl = GetDlgItem(wnd, id); - if (lbl == NULL) - error::raise("GetDlgItem"); - return lbl; - } +namespace { - bool is_administrator() - { - auto token = token::open_for_current_process( - token::permissions::query() | token::permissions::duplicate()); - if (!token::get_linked(token)) - token = token::get_for_identification(token); +HWND get_dialog_item(HWND wnd, int id) { + const auto lbl = GetDlgItem(wnd, id); + if (lbl == NULL) + error::raise("GetDlgItem"); + return lbl; +} - return token::check_belongs(token, sid::builtin_administrators()); - } +bool is_administrator() { + auto token = token::open_for_current_process(token::permissions::query() | + token::permissions::duplicate()); + if (!token::get_linked(token)) + token = token::get_for_identification(token); - bool is_run_as_administrator() - { - return token::check_belongs(token::dumb(), sid::builtin_administrators()); - } + return token::check_belongs(token, sid::builtin_administrators()); +} - bool is_elevated() - { - return token::query_elevation(token::open_for_current_process()); - } +bool is_run_as_administrator() { + return token::check_belongs(token::dumb(), sid::builtin_administrators()); +} - void decorate_elevate_button(HWND wnd, bool decorate) - { - const auto btn = get_dialog_item(wnd, IDC_BUTTON_ELEVATE); - Button_SetElevationRequiredState(btn, !decorate); - } +bool is_elevated() { + return token::query_elevation(token::open_for_current_process()); +} - DWORD get_integrity_level() - { - return token::query_integrity_level(token::open_for_current_process()); - } +void decorate_elevate_button(HWND wnd, bool decorate) { + const auto btn = get_dialog_item(wnd, IDC_BUTTON_ELEVATE); + Button_SetElevationRequiredState(btn, !decorate); +} - std::wstring get_integrity_level_as_string() - { - return token::integrity_level_to_string(get_integrity_level()); - } +DWORD get_integrity_level() { + return token::query_integrity_level(token::open_for_current_process()); +} - HWND get_label(HWND wnd, int id) - { - return get_dialog_item(wnd, id); - } +std::wstring get_integrity_level_as_string() { + return token::integrity_level_to_string(get_integrity_level()); +} - void set_label(HWND wnd, int id, bool val) - { - SetWindowTextW(get_label(wnd, id), val ? L"True" : L"False"); - } +HWND get_label(HWND wnd, int id) { + return get_dialog_item(wnd, id); +} + +void set_label(HWND wnd, int id, bool val) { + SetWindowTextW(get_label(wnd, id), val ? L"True" : L"False"); +} + +void set_label(HWND wnd, int id, const wchar_t* s) { + SetWindowTextW(get_label(wnd, id), s); +} - void set_label(HWND wnd, int id, const wchar_t* s) - { - SetWindowTextW(get_label(wnd, id), s); +void set_label(HWND wnd, int id, const std::wstring& s) { + SetWindowTextW(get_label(wnd, id), s.c_str()); +} + +BOOL on_init_dialog(HWND wnd, HWND, LPARAM) { + try { + set_label(wnd, IDC_ADMINISTRATOR, is_administrator()); + } catch (const Error& e) { + set_label(wnd, IDC_ADMINISTRATOR, L"N/A"); + error::report(e); } - void set_label(HWND wnd, int id, const std::wstring& s) - { - SetWindowTextW(get_label(wnd, id), s.c_str()); + try { + set_label(wnd, IDC_RUN_AS_ADMINISTRATOR, is_run_as_administrator()); + } catch (const Error& e) { + set_label(wnd, IDC_RUN_AS_ADMINISTRATOR, L"N/A"); + error::report(e); } - BOOL on_init_dialog(HWND wnd, HWND, LPARAM) - { - try - { - set_label(wnd, IDC_ADMINISTRATOR, is_administrator()); - } - catch (const Error& e) - { - set_label(wnd, IDC_ADMINISTRATOR, L"N/A"); + if (os::is_vista_or_later()) { + try { + const auto elevated = is_elevated(); + set_label(wnd, IDC_ELEVATED, elevated); + decorate_elevate_button(wnd, elevated); + } catch (const Error& e) { + set_label(wnd, IDC_ELEVATED, L"N/A"); error::report(e); } - try - { - set_label(wnd, IDC_RUN_AS_ADMINISTRATOR, is_run_as_administrator()); - } - catch (const Error& e) - { - set_label(wnd, IDC_RUN_AS_ADMINISTRATOR, L"N/A"); + try { + set_label(wnd, IDC_INTEGRITY_LEVEL, get_integrity_level_as_string()); + } catch (const Error& e) { + set_label(wnd, IDC_INTEGRITY_LEVEL, L"N/A"); error::report(e); } + } else { + set_label(wnd, IDC_ELEVATED, L"N/A"); + set_label(wnd, IDC_INTEGRITY_LEVEL, L"N/A"); + } - if (os::is_vista_or_later()) - { - try - { - const auto elevated = is_elevated(); - set_label(wnd, IDC_ELEVATED, elevated); - decorate_elevate_button(wnd, elevated); - } - catch (const Error& e) - { - set_label(wnd, IDC_ELEVATED, L"N/A"); - error::report(e); - } - - try - { - set_label(wnd, IDC_INTEGRITY_LEVEL, get_integrity_level_as_string()); - } - catch (const Error& e) - { - set_label(wnd, IDC_INTEGRITY_LEVEL, L"N/A"); - error::report(e); - } - } - else - { - set_label(wnd, IDC_ELEVATED, L"N/A"); - set_label(wnd, IDC_INTEGRITY_LEVEL, L"N/A"); - } + return TRUE; +} - return TRUE; - } +void report_already_elevated(HWND wnd) { + MessageBoxW(wnd, + resource::load_string(IDS_ALREADY_ELEVATED_TEXT).c_str(), + resource::load_string(IDS_ALREADY_ELEVATED_CAPTION).c_str(), + MB_OK); +} + +void on_button_elevate_click(HWND wnd) { + bool as_admin = false; - void report_already_elevated(HWND wnd) - { - MessageBoxW(wnd, - resource::load_string(IDS_ALREADY_ELEVATED_TEXT).c_str(), - resource::load_string(IDS_ALREADY_ELEVATED_CAPTION).c_str(), - MB_OK); + try { + as_admin = is_run_as_administrator(); + } catch (const Error& e) { + error::report(e); + return; } - void on_button_elevate_click(HWND wnd) - { - bool as_admin = false; + if (as_admin) { + report_already_elevated(wnd); + return; + } - try - { - as_admin = is_run_as_administrator(); - } - catch (const Error& e) - { + try { + process::runas_self(wnd); + } catch (const Error& e) { + if (error::get_code(e) != ERROR_CANCELLED) error::report(e); - return; - } - - if (as_admin) - { - report_already_elevated(wnd); - return; - } + return; + } - try - { - process::runas_self(wnd); - } - catch (const Error& e) - { - if (error::get_code(e) != ERROR_CANCELLED) - error::report(e); - return; - } + EndDialog(wnd, 1); +} - EndDialog(wnd, 1); - } +void on_command(HWND wnd, int id, HWND, unsigned int) { + switch (id) { + case IDC_BUTTON_ELEVATE: + on_button_elevate_click(wnd); + break; - void on_command(HWND wnd, int id, HWND, unsigned int) - { - switch (id) - { - case IDC_BUTTON_ELEVATE: - on_button_elevate_click(wnd); - break; - - case IDOK: - case IDCANCEL: - EndDialog(wnd, 0); - break; - } + case IDOK: + case IDCANCEL: + EndDialog(wnd, 0); + break; } +} - void on_close(HWND wnd) - { - EndDialog(wnd, 0); - } +void on_close(HWND wnd) { + EndDialog(wnd, 0); +} - INT_PTR CALLBACK dialog_main( - HWND wnd, - UINT msg, - WPARAM wParam, - LPARAM lParam) - { - switch (msg) - { - HANDLE_MSG(wnd, WM_INITDIALOG, on_init_dialog); - HANDLE_MSG(wnd, WM_COMMAND, on_command); - HANDLE_MSG(wnd, WM_CLOSE, on_close); +INT_PTR CALLBACK dialog_main(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + HANDLE_MSG(wnd, WM_INITDIALOG, on_init_dialog); + HANDLE_MSG(wnd, WM_COMMAND, on_command); + HANDLE_MSG(wnd, WM_CLOSE, on_close); - default: - return FALSE; - } + default: + return FALSE; } } -int APIENTRY wWinMain( - HINSTANCE instance, - HINSTANCE, - wchar_t*, - int) -{ - try - { - const auto ret = DialogBoxW( - instance, - MAKEINTRESOURCE(IDD_MAINDIALOG), - NULL, - dialog_main); - - switch (ret) - { +} // namespace + +int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) { + try { + const auto ret = DialogBoxW(instance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, dialog_main); + + switch (ret) { case -1: error::report(error::make("DialogBoxW")); default: return static_cast(ret); } - } - catch (const std::exception& e) - { + } catch (const std::exception& e) { error::report(e); return 1; } diff --git a/src/os.hpp b/src/os.hpp index f6f169f..1ec023e 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -9,27 +9,25 @@ #include -namespace os -{ - inline OSVERSIONINFOW get_version_info() - { - OSVERSIONINFOW info; - ZeroMemory(&info, sizeof(info)); - info.dwOSVersionInfoSize = sizeof(info); - - if (!GetVersionExW(&info)) - error::raise("GetVersionExW"); - - return info; - } - - inline bool is_vista_or_later(const OSVERSIONINFOW& info) - { - return info.dwMajorVersion >= 6; - } - - inline bool is_vista_or_later() - { - return is_vista_or_later(get_version_info()); - } +namespace os { + +inline OSVERSIONINFOW get_version_info() { + OSVERSIONINFOW info; + ZeroMemory(&info, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + + if (!GetVersionExW(&info)) + error::raise("GetVersionExW"); + + return info; +} + +inline bool is_vista_or_later(const OSVERSIONINFOW& info) { + return info.dwMajorVersion >= 6; +} + +inline bool is_vista_or_later() { + return is_vista_or_later(get_version_info()); } + +} // namespace os diff --git a/src/process.cpp b/src/process.cpp index a2eddc0..b71bff0 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -3,60 +3,54 @@ // For details, see https://github.com/egor-tensin/privilege-check. // Distributed under the MIT License. +#include "process.hpp" + #include "cmd_line.hpp" #include "error.hpp" -#include "process.hpp" +/* clang-format off */ #include #include +/* clang-format on */ #include #include -namespace process -{ - std::wstring get_executable_path() - { - static constexpr DWORD max_path = MAX_PATH; - - std::array buf; - - const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); - - if (ret != ERROR_SUCCESS) - error::raise("GetModuleFileNameW"); - - return buf.data(); - } - - void runas( - const CommandLine& cmd_line, - HWND hwnd, - int nShow) - { - const auto exe_path = cmd_line.has_argv0() - ? cmd_line.get_argv0() - : get_executable_path(); - - SHELLEXECUTEINFOW info; - ZeroMemory(&info, sizeof(info)); - info.cbSize = sizeof(info); - info.lpVerb = L"runas"; - info.lpFile = exe_path.c_str(); - const auto args = cmd_line.join_args(); - if (!args.empty()) - info.lpParameters = args.c_str(); - info.hwnd = hwnd; - info.nShow = nShow; - - if (!ShellExecuteExW(&info)) - error::raise("ShellExecuteExW"); - } - - void runas_self( - HWND hwnd, - int nShow) - { - runas(CommandLine::query(), hwnd, nShow); - } +namespace process { + +std::wstring get_executable_path() { + static constexpr DWORD max_path = MAX_PATH; + + std::array buf; + + const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); + + if (ret != ERROR_SUCCESS) + error::raise("GetModuleFileNameW"); + + return buf.data(); +} + +void runas(const CommandLine& cmd_line, HWND hwnd, int nShow) { + const auto exe_path = cmd_line.has_argv0() ? cmd_line.get_argv0() : get_executable_path(); + + SHELLEXECUTEINFOW info; + ZeroMemory(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = L"runas"; + info.lpFile = exe_path.c_str(); + const auto args = cmd_line.join_args(); + if (!args.empty()) + info.lpParameters = args.c_str(); + info.hwnd = hwnd; + info.nShow = nShow; + + if (!ShellExecuteExW(&info)) + error::raise("ShellExecuteExW"); } + +void runas_self(HWND hwnd, int nShow) { + runas(CommandLine::query(), hwnd, nShow); +} + +} // namespace process diff --git a/src/process.hpp b/src/process.hpp index c27dc3e..9ad93d9 100644 --- a/src/process.hpp +++ b/src/process.hpp @@ -5,36 +5,30 @@ #pragma once -#include "error.hpp" #include "cmd_line.hpp" +#include "error.hpp" #include #include -namespace process -{ - inline HMODULE load_exe_module() - { - const auto module = GetModuleHandle(NULL); - if (module == NULL) - error::raise("GetModuleHandle"); - return module; - } - - std::wstring get_executable_path(); - - inline std::wstring get_command_line() - { - return GetCommandLine(); - } - - void runas( - const CommandLine& cmd_line, - HWND hwnd = NULL, - int nShow = SW_NORMAL); - - void runas_self( - HWND hwnd = NULL, - int nShow = SW_NORMAL); +namespace process { + +inline HMODULE load_exe_module() { + const auto module = GetModuleHandle(NULL); + if (module == NULL) + error::raise("GetModuleHandle"); + return module; } + +std::wstring get_executable_path(); + +inline std::wstring get_command_line() { + return GetCommandLine(); +} + +void runas(const CommandLine& cmd_line, HWND hwnd = NULL, int nShow = SW_NORMAL); + +void runas_self(HWND hwnd = NULL, int nShow = SW_NORMAL); + +} // namespace process diff --git a/src/resource.hpp b/src/resource.hpp index 6039fab..1f7b9ad 100644 --- a/src/resource.hpp +++ b/src/resource.hpp @@ -11,24 +11,19 @@ #include #include - #include -namespace resource -{ - inline std::wstring load_string(unsigned int id) - { - wchar_t* s = nullptr; +namespace resource { + +inline std::wstring load_string(unsigned int id) { + wchar_t* s = nullptr; - const auto ret = LoadStringW( - process::load_exe_module(), - id, - reinterpret_cast(&s), - 0); + const auto ret = LoadStringW(process::load_exe_module(), id, reinterpret_cast(&s), 0); - if (ret <= 0) - error::raise("LoadStringW"); + if (ret <= 0) + error::raise("LoadStringW"); - return {s, static_cast(ret)}; - } + return {s, static_cast(ret)}; } + +} // namespace resource diff --git a/src/sid.cpp b/src/sid.cpp index 7a0e252..1a69763 100644 --- a/src/sid.cpp +++ b/src/sid.cpp @@ -3,69 +3,69 @@ // For details, see https://github.com/egor-tensin/privilege-check. // Distributed under the MIT License. -#include "error.hpp" #include "sid.hpp" +#include "error.hpp" + +/* clang-format off */ #include #include +/* clang-format on */ #include #include -namespace sid -{ - SidBuffer well_known(WELL_KNOWN_SID_TYPE type) - { - SidBuffer buffer; - DWORD cb = static_cast(buffer.size()); +namespace sid { - if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) - error::raise("CreateWellKnownSid"); +SidBuffer well_known(WELL_KNOWN_SID_TYPE type) { + SidBuffer buffer; + DWORD cb = static_cast(buffer.size()); - return buffer; - } + if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) + error::raise("CreateWellKnownSid"); - SidBuffer builtin_administrators() - { - /* - void* sid = nullptr; - SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; - - if (!AllocateAndInitializeSid( - &authority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &sid)) - { - error::raise("AllocateAndInitializeSid"); - } - - return std::unique_ptr{sid}; - */ - - return well_known(WinBuiltinAdministratorsSid); - } + return buffer; +} + +SidBuffer builtin_administrators() { + /* + void* sid = nullptr; + SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; - namespace + if (!AllocateAndInitializeSid( + &authority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid)) { - struct LocalDelete - { - void operator()(wchar_t* s) const - { - LocalFree(s); - } - }; + error::raise("AllocateAndInitializeSid"); } - std::wstring to_string(const SidBuffer& sid) - { - wchar_t* s = nullptr; + return std::unique_ptr{sid}; + */ + + return well_known(WinBuiltinAdministratorsSid); +} - if (!ConvertSidToStringSidW(const_cast(sid.data()), &s)) - error::raise("ConvertSidToStringSidW"); +namespace { - return std::unique_ptr{s}.get(); +struct LocalDelete { + void operator()(wchar_t* s) const { + LocalFree(s); } +}; + +} // namespace + +std::wstring to_string(const SidBuffer& sid) { + wchar_t* s = nullptr; + + if (!ConvertSidToStringSidW(const_cast(sid.data()), &s)) + error::raise("ConvertSidToStringSidW"); + + return std::unique_ptr{s}.get(); } + +} // namespace sid diff --git a/src/sid.hpp b/src/sid.hpp index 2dc6111..a890e48 100644 --- a/src/sid.hpp +++ b/src/sid.hpp @@ -5,8 +5,10 @@ #pragma once +/* clang-format off */ #include #include +/* clang-format on */ #include #include @@ -15,11 +17,12 @@ constexpr DWORD max_sid_size = SECURITY_MAX_SID_SIZE; typedef std::array SidBuffer; -namespace sid -{ - SidBuffer well_known(WELL_KNOWN_SID_TYPE type); +namespace sid { - SidBuffer builtin_administrators(); +SidBuffer well_known(WELL_KNOWN_SID_TYPE type); - std::wstring to_string(const SidBuffer&); -} +SidBuffer builtin_administrators(); + +std::wstring to_string(const SidBuffer&); + +} // namespace sid diff --git a/src/string.hpp b/src/string.hpp index 24d0425..dee1966 100644 --- a/src/string.hpp +++ b/src/string.hpp @@ -5,155 +5,136 @@ #pragma once +#include #include #include - -#include #include #include #include #include #include -namespace string -{ - template - void ltrim(std::basic_string& s) - { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [] (const Char& c) - { - return !std::isspace(c); - })); - } +namespace string { - template - void rtrim(std::basic_string& s) - { - s.erase(std::find_if(s.rbegin(), s.rend(), [] (const Char& c) - { - return !std::isspace(c); - }).base(), s.end()); - } +template +void ltrim(std::basic_string& s) { + s.erase(s.begin(), + std::find_if(s.begin(), s.end(), [](const Char& c) { return !std::isspace(c); })); +} + +template +void rtrim(std::basic_string& s) { + s.erase( + std::find_if(s.rbegin(), s.rend(), [](const Char& c) { return !std::isspace(c); }).base(), + s.end()); +} + +template +void trim(std::basic_string& s) { + ltrim(s); + rtrim(s); +} + +template +std::basic_string join(const Sep& sep, InputIterator beg, InputIterator end) { + std::basic_ostringstream oss; - template - void trim(std::basic_string& s) - { - ltrim(s); - rtrim(s); + if (beg != end) { + oss << *beg; + ++beg; } - template - std::basic_string join( - const Sep& sep, - InputIterator beg, - InputIterator end) - { - std::basic_ostringstream oss; + for (; beg != end; ++beg) + oss << sep << *beg; + + return oss.str(); +} + +template +std::basic_string join(const Sep& sep, const std::vector>& args) { + return join(sep, args.cbegin(), args.cend()); +} + +template +struct StringHelper {}; - if (beg != end) - { - oss << *beg; - ++beg; - } +template +struct StringHelper::type>::type, + Char>::value>::type> { + StringHelper(const Char& c) : buf{&c}, len{1} {} - for (; beg != end; ++beg) - oss << sep << *beg; + StringHelper(const Char* s) : buf{s}, len{std::char_traits::length(s)} {} - return oss.str(); + const Char* buffer() const { + return buf; } - template - std::basic_string join( - const Sep& sep, - const std::vector>& args) - { - return join(sep, args.cbegin(), args.cend()); + std::size_t length() const { + return len; } - template - struct StringHelper - { }; - - template - struct StringHelper::type>::type, Char>::value>::type> - { - StringHelper(const Char& c) - : buf{&c} - , len{1} - { } - - StringHelper(const Char* s) - : buf{s} - , len{std::char_traits::length(s)} - { } - - const Char* buffer() const { return buf; } - - std::size_t length() const { return len; } - - private: - const Char* const buf; - const std::size_t len; - }; - - template - struct StringHelper>::value>::type> - { - StringHelper(const std::basic_string& s) - : s{s} - { } - - const Char* buffer() const { return s.c_str(); } - - std::size_t length() const { return s.length(); } - - private: - const std::basic_string& s; - }; - - template - void replace( - std::basic_string& s, - const What& what, - const By& by) - { - std::size_t pos = 0; - - const StringHelper::type> what_helper{what}; - const StringHelper::type> by_helper{by}; - - const auto what_buf = what_helper.buffer(); - const auto what_len = what_helper.length(); - - const auto by_buf = by_helper.buffer(); - const auto by_len = by_helper.length(); - - while ((pos = s.find(what_buf, pos, what_len)) != std::basic_string::npos) - { - s.replace(pos, what_len, by_buf, by_len); - pos += by_len; - } +private: + const Char* const buf; + const std::size_t len; +}; + +template +struct StringHelper< + Char, + String, + typename std::enable_if>::value>::type> { + StringHelper(const std::basic_string& s) : s{s} {} + + const Char* buffer() const { + return s.c_str(); } - template - void prefix_with( - std::basic_string& s, - const What& what, - const Char& by) - { - const StringHelper::type> what_helper{what}; + std::size_t length() const { + return s.length(); + } + +private: + const std::basic_string& s; +}; - const auto what_buf = what_helper.buffer(); - const auto what_len = what_helper.length(); +template +void replace(std::basic_string& s, const What& what, const By& by) { + std::size_t pos = 0; - std::size_t numof_by = 0; + const StringHelper::type> what_helper{what}; + const StringHelper::type> by_helper{by}; - for (std::size_t i = 0; i < what_len; ++i) - numof_by += std::count(s.cbegin(), s.cend(), what_buf[i]); + const auto what_buf = what_helper.buffer(); + const auto what_len = what_helper.length(); - s.reserve(s.capacity() + numof_by); + const auto by_buf = by_helper.buffer(); + const auto by_len = by_helper.length(); - for (std::size_t i = 0; i < what_len; ++i) - replace(s, what_buf[i], by); + while ((pos = s.find(what_buf, pos, what_len)) != std::basic_string::npos) { + s.replace(pos, what_len, by_buf, by_len); + pos += by_len; } } + +template +void prefix_with(std::basic_string& s, const What& what, const Char& by) { + const StringHelper::type> what_helper{what}; + + const auto what_buf = what_helper.buffer(); + const auto what_len = what_helper.length(); + + std::size_t numof_by = 0; + + for (std::size_t i = 0; i < what_len; ++i) + numof_by += std::count(s.cbegin(), s.cend(), what_buf[i]); + + s.reserve(s.capacity() + numof_by); + + for (std::size_t i = 0; i < what_len; ++i) + replace(s, what_buf[i], by); +} + +} // namespace string diff --git a/src/token.cpp b/src/token.cpp index f7ad38e..1333290 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -3,6 +3,8 @@ // For details, see https://github.com/egor-tensin/privilege-check. // Distributed under the MIT License. +#include "token.hpp" + #include "error.hpp" #include "handle.hpp" #include "os.hpp" @@ -15,153 +17,140 @@ #include #include -namespace token -{ - Handle open_for_process( - const Handle& process, - DWORD permissions) - { - HANDLE raw; +namespace token { - if (!OpenProcessToken(process, permissions, &raw)) - error::raise("OpenProcessToken"); +Handle open_for_process(const Handle& process, DWORD permissions) { + HANDLE raw; - return Handle{raw}; - } + if (!OpenProcessToken(process, permissions, &raw)) + error::raise("OpenProcessToken"); - Handle open_for_current_process( - DWORD permissions) - { - return open_for_process(Handle{GetCurrentProcess()}, permissions); - } + return Handle{raw}; +} + +Handle open_for_current_process(DWORD permissions) { + return open_for_process(Handle{GetCurrentProcess()}, permissions); +} - bool get_linked(Handle& token) - { - if (!os::is_vista_or_later()) - return false; +bool get_linked(Handle& token) { + if (!os::is_vista_or_later()) + return false; - auto type = TokenElevationTypeDefault; - DWORD cb = 0; + auto type = TokenElevationTypeDefault; + DWORD cb = 0; - if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) - error::raise("GetTokenInformation"); + if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) + error::raise("GetTokenInformation"); - if (type != TokenElevationTypeLimited) - return false; + if (type != TokenElevationTypeLimited) + return false; - HANDLE raw; + HANDLE raw; - if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) - error::raise("GetTokenInformation"); + if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) + error::raise("GetTokenInformation"); - token = Handle{raw}; - return true; - } + token = Handle{raw}; + return true; +} - Handle get_for_identification(const Handle& token) - { - HANDLE raw; +Handle get_for_identification(const Handle& token) { + HANDLE raw; - if (!DuplicateToken(token, SecurityIdentification, &raw)) - error::raise("DuplicateToken"); + if (!DuplicateToken(token, SecurityIdentification, &raw)) + error::raise("DuplicateToken"); - return Handle{raw}; - } + return Handle{raw}; +} - // - // FUNCTION: query_integrity_level() - // - // RETURN VALUE: Returns the integrity level of the current process. It is - // usually one of these values: - // - // SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) - // Means untrusted level. It is used by processes started by the - // Anonymous group. Blocks most write access. - // - // SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) - // Means low integrity level. It is used by Protected Mode Internet - // Explorer. Blocks write acess to most objects (such as files and - // registry keys) on the system. - // - // SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) - // Means medium integrity level. It is used by normal applications - // being launched while UAC is enabled. - // - // SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) - // Means high integrity level. It is used by administrative applications - // launched through elevation when UAC is enabled, or normal - // applications if UAC is disabled and the user is an administrator. - // - // SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) - // Means system integrity level. It is used by services and other - // system-level applications (such as Wininit, Winlogon, Smss, etc.) - // - DWORD query_integrity_level(const Handle& token) - { - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) - { - switch (GetLastError()) - { - case ERROR_INSUFFICIENT_BUFFER: - break; - default: - error::raise("GetTokenInformation"); - } +// +// FUNCTION: query_integrity_level() +// +// RETURN VALUE: Returns the integrity level of the current process. It is +// usually one of these values: +// +// SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) +// Means untrusted level. It is used by processes started by the +// Anonymous group. Blocks most write access. +// +// SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) +// Means low integrity level. It is used by Protected Mode Internet +// Explorer. Blocks write acess to most objects (such as files and +// registry keys) on the system. +// +// SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) +// Means medium integrity level. It is used by normal applications +// being launched while UAC is enabled. +// +// SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) +// Means high integrity level. It is used by administrative applications +// launched through elevation when UAC is enabled, or normal +// applications if UAC is disabled and the user is an administrator. +// +// SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) +// Means system integrity level. It is used by services and other +// system-level applications (such as Wininit, Winlogon, Smss, etc.) +// +DWORD query_integrity_level(const Handle& token) { + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) { + switch (GetLastError()) { + case ERROR_INSUFFICIENT_BUFFER: + break; + default: + error::raise("GetTokenInformation"); } + } - std::vector buf(cb); - const auto token_level = reinterpret_cast(buf.data()); + std::vector buf(cb); + const auto token_level = reinterpret_cast(buf.data()); - if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) - error::raise("GetTokenInformation"); + if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) + error::raise("GetTokenInformation"); - // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. - // S-1-16-0x1000 stands for low integrity level SID). There is one and - // only one subauthority. - return *GetSidSubAuthority(token_level->Label.Sid, 0); - } + // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. + // S-1-16-0x1000 stands for low integrity level SID). There is one and + // only one subauthority. + return *GetSidSubAuthority(token_level->Label.Sid, 0); +} - std::wstring integrity_level_to_string(DWORD level) - { - static const std::unordered_map names = - { - {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, - {SECURITY_MANDATORY_LOW_RID, L"Low"}, - {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, - {SECURITY_MANDATORY_HIGH_RID, L"High"}, - {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, - }; +std::wstring integrity_level_to_string(DWORD level) { + static const std::unordered_map names = { + {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, + {SECURITY_MANDATORY_LOW_RID, L"Low"}, + {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, + {SECURITY_MANDATORY_HIGH_RID, L"High"}, + {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, + }; - static constexpr auto unknown_name = L"Unknown"; + static constexpr auto unknown_name = L"Unknown"; - const auto it = names.find(level); + const auto it = names.find(level); - if (it == names.cend()) - return unknown_name; + if (it == names.cend()) + return unknown_name; - return it->second; - } + return it->second; +} - bool check_belongs(const Handle& token, const SidBuffer& sid) - { - BOOL b = FALSE; +bool check_belongs(const Handle& token, const SidBuffer& sid) { + BOOL b = FALSE; - if (!CheckTokenMembership(token, const_cast(sid.data()), &b)) - error::raise("CheckTokenMembership"); + if (!CheckTokenMembership(token, const_cast(sid.data()), &b)) + error::raise("CheckTokenMembership"); - return b != FALSE; - } + return b != FALSE; +} - bool query_elevation(const Handle& token) - { - TOKEN_ELEVATION elevation; - DWORD cb = 0; +bool query_elevation(const Handle& token) { + TOKEN_ELEVATION elevation; + DWORD cb = 0; - if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) - error::raise("GetTokenInformation"); + if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) + error::raise("GetTokenInformation"); - return elevation.TokenIsElevated != 0; - } + return elevation.TokenIsElevated != 0; } + +} // namespace token diff --git a/src/token.hpp b/src/token.hpp index 5ad32bf..2ccee13 100644 --- a/src/token.hpp +++ b/src/token.hpp @@ -12,36 +12,40 @@ #include -namespace token -{ - namespace permissions - { - constexpr DWORD query() { return TOKEN_QUERY; } +namespace token { +namespace permissions { - constexpr DWORD duplicate() { return TOKEN_DUPLICATE; } - } +constexpr DWORD query() { + return TOKEN_QUERY; +} - constexpr DWORD default_permissions = permissions::query(); +constexpr DWORD duplicate() { + return TOKEN_DUPLICATE; +} - // Current thread's primary impersonation token. - inline Handle dumb() { return Handle{NULL}; } +} // namespace permissions - Handle open_for_process( - const Handle& process, - DWORD permissions = default_permissions); +constexpr DWORD default_permissions = permissions::query(); - Handle open_for_current_process( - DWORD permissions = default_permissions); +// Current thread's primary impersonation token. +inline Handle dumb() { + return Handle{NULL}; +} - bool get_linked(Handle& token); +Handle open_for_process(const Handle& process, DWORD permissions = default_permissions); - Handle get_for_identification(const Handle& token); +Handle open_for_current_process(DWORD permissions = default_permissions); - DWORD query_integrity_level(const Handle& token); +bool get_linked(Handle& token); - std::wstring integrity_level_to_string(DWORD); +Handle get_for_identification(const Handle& token); - bool check_belongs(const Handle& token, const SidBuffer& sid); +DWORD query_integrity_level(const Handle& token); - bool query_elevation(const Handle& token); -} +std::wstring integrity_level_to_string(DWORD); + +bool check_belongs(const Handle& token, const SidBuffer& sid); + +bool query_elevation(const Handle& token); + +} // namespace token -- cgit v1.3