Hi guys, how do I trigger a new process to be run as admin?

Hi guys, how do I trigger a new process to be run as admin using Rust?

I'm not really the expert on this, but it's 2am so my speed of response hopefully makes up for that I might be wrong.

I think it inherits permissions from the parent process, so if you want rust to spawn a process as admin then you just need to run the rust executable as admin.

The same as using any other language - with OS-specific functions.

Assuming this is Windows and you’re trying to run a program as admin from a normal program, the easiest API is ShellExecuteW with the "runas" action. With Microsoft’s Windows API for Rust, this would be something like:

mod bindings {
    windows::include_bindings!();
}

use bindings::Windows::Win32::System::SystemServices::PWSTR;
use bindings::Windows::Win32::UI::Shell::ShellExecuteW;
use bindings::Windows::Win32::UI::WindowsAndMessaging::HWND;

fn main() {
    windows::initialize_sta().unwrap();
    let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
    if r.0 < 32 {
        println!("error: {:?}", r);
    }
}
1 Like

Erm, I think you may want to UTF-16 encode and null terminate those strings?

windows-rs is very clever. In this case, the parameter has the type IntoParam<'_, PWSTR>, and there is an implementation of this for &str that does the UTF-16 encoding and null-termination, collects the result into a Vec<u16>, converts that to a Box<[u16]> and passes that as a pointer to the Windows API.

impl<'a> ::windows::IntoParam<'a, PWSTR> for &'a str {
    fn into_param(self) -> ::windows::Param<'a, PWSTR> {
        ::windows::Param::Boxed(PWSTR(::std::boxed::Box::<[u16]>::into_raw(
            self.encode_utf16()
                .chain(::std::iter::once(0))
                .collect::<std::vec::Vec<u16>>()
                .into_boxed_slice(),
        ) as _))
    }
}
5 Likes

Oh great, that is useful!

Hey mate, what library am I importing because it fails to build.

I get the following errors:

error[E0433]: failed to resolve: could not find `Windows` in `bindings`
 --> src\main.rs:6:15
  |
6 | use bindings::Windows::Win32::System::SystemServices::PWSTR;       
  |               ^^^^^^^ could not find `Windows` in `bindings`

error[E0433]: failed to resolve: could not find `Windows` in `bindings`
 --> src\main.rs:7:15
  |
7 | use bindings::Windows::Win32::UI::Shell::ShellExecuteW;
  |               ^^^^^^^ could not find `Windows` in `bindings`

error[E0433]: failed to resolve: could not find `Windows` in `bindings`
 --> src\main.rs:8:15
  |
8 | use bindings::Windows::Win32::UI::WindowsAndMessaging::HWND;
  |               ^^^^^^^ could not find `Windows` in `bindings`

error[E0433]: failed to resolve: use of undeclared crate or module `windows`
 --> src\main.rs:3:5
  |
3 |     windows::include_bindings!();
  |     ^^^^^^^ use of undeclared crate or module `windows`

error[E0433]: failed to resolve: use of undeclared crate or module `windows`
  --> src\main.rs:12:5
   |
12 |     windows::initialize_sta().unwrap();
   |     ^^^^^^^ use of undeclared crate or module `windows`

error[E0433]: failed to resolve: use of undeclared type `HWND`
  --> src\main.rs:13:36
   |
13 |     let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
   |                                    ^^^^ use of undeclared type `HWND`

error[E0433]: failed to resolve: use of undeclared type `PWSTR`
  --> src\main.rs:13:91
   |
13 |     let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
   |                                                                                           ^^^^^ use of undeclared type `PWSTR`

error[E0433]: failed to resolve: use of undeclared type `PWSTR`
  --> src\main.rs:13:104
   |
13 |     let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
   |                                                                                                        ^^^^^ use of undeclared type `PWSTR`

error[E0425]: cannot find function, tuple struct or tuple variant `ShellExecuteW` in this scope
  --> src\main.rs:13:22
   |
13 |     let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
   |                      ^^^^^^^^^^^^^ not found in this scope

error: aborting due to 9 previous errors

Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `learning`

To learn more, run the command again with --verbose.

after using your code:

mod bindings {
    windows::include_bindings!();
}

use bindings::Windows::Win32::System::SystemServices::PWSTR;
use bindings::Windows::Win32::UI::Shell::ShellExecuteW;
use bindings::Windows::Win32::UI::WindowsAndMessaging::HWND;

fn main() {
    windows::initialize_sta().unwrap();
    let r = unsafe { ShellExecuteW(HWND::NULL, "runas", "C:\\Windows\\System32\\cmd.exe", PWSTR::NULL, PWSTR::NULL, 1) };
    if r.0 < 32 {
        println!("error: {:?}", r);
    }
}

I left out a bit of the setup that’s described at GitHub - microsoft/windows-rs: Rust for Windows. You need to add the dependencies to Cargo.toml, as both normal and build dependencies:

[dependencies]
windows = "0.10.0"

[build-dependencies]
windows = "0.10.0"

and you need a build.rs in the same directory as Cargo.toml which will generate the APIs:

fn main() {
    windows::build!(
        Windows::Win32::UI::Shell::ShellExecuteW
    );
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.