aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/src/main.cpp
blob: be8d5e7609608a05d6e4cc542454468a2d7a9d5e (plain) (tree)
1
2
3
4
5
6
7
8
9




                                                                  


                      
                       
                         

                    








                                                                                                                                                                                                   







                                         
                       
 



                                                                       
 
                                                                      



                              
                                                                              



                  
                                                                     

 





                                                              
                           
 
                                                                           






                                                                   




                                    

                                          
                                                                 

 
                                                  
 
                                          

 
                                                       
 
                                                  





                                           
                                                              


                          
                                                  




                         
                                                                            


                          
                                                         







                                                
                                                   
                                                   


                              
                                                 




                             
                                                                                 


                              
                                                        




                             

                                                    




                


                                      

                                                                    


               
                                      
 


                          
     






                                             
 

                 
                                     

               
 

       
                                                            






                                                  
 








                                                     
                  



































                                                       
                                


                                        




                     
                                                     


                                         
 
// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com>
// This file is part of the "Privilege test" project.
// For details, see https://github.com/egor-tensin/privilege-test.
// Distributed under the MIT License.

#include "error.hpp"
#include "os.hpp"
#include "process.hpp"
#include "resource.hpp"
#include "resource_ids.h"
#include "sid.hpp"
#include "token.hpp"

#include <Windows.h>
#include <CommCtrl.h>
#include <windowsx.h>

#include <string>

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

HWND get_dialog_item(HWND wnd, int id)
{
    const auto lbl = GetDlgItem(wnd, id);
    if (lbl == NULL)
        error::raise("GetDlgItem");
    return lbl;
}

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);

    return token::check_belongs(token, sid::builtin_administrators());
}

bool is_run_as_administrator()
{
    return token::check_belongs(token::dumb(), sid::builtin_administrators());
}

bool is_elevated()
{
    return token::query_elevation(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);
}

DWORD get_integrity_level()
{
    return token::query_integrity_level(token::open_for_current_process());
}

std::wstring get_integrity_level_as_string()
{
    return token::integrity_level_to_string(get_integrity_level());
}

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 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);
    }

    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);
    }

    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;
}

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;

    try
    {
        as_admin = is_run_as_administrator();
    }
    catch (const Error& e)
    {
        error::report(e);
        return;
    }

    if (as_admin)
    {
        report_already_elevated(wnd);
        return;
    }

    try
    {
        process::runas(process::get_executable_path(), wnd);
    }
    catch (const Error& e)
    {
        if (error::get_code(e) != ERROR_CANCELLED)
            error::report(e);
        return;
    }

    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;

        case IDOK:
        case IDCANCEL:
            EndDialog(wnd, 0);
            break;
    }
}

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);

        default:
            return FALSE;
    }
}

int APIENTRY wWinMain(
    HINSTANCE instance,
    HINSTANCE,
    wchar_t*,
    int)
{
    const auto ret = DialogBoxW(
        instance,
        MAKEINTRESOURCE(IDD_MAINDIALOG),
        NULL,
        dialog_main);

    switch (ret)
    {
        case -1:
            error::report(error::make("DialogBoxW"));
        default:
            return static_cast<int>(ret);
    }
}