Create system restore point

Good morning, everyone,

I begin with rust, I find this language incredible but it's hard for me. I have some questions:

  • What's the best way to create a restore point on Windows with rust?

  • Is there an implementation of srrestoreptapi?

  • I try to reproduce this C++ code with rust but I get a code 87 which corresponds to a ERROR_INVALID_PARAMETER

My script:

extern crate winapi;

use std::ptr;

use winapi::shared::minwindef::{LPVOID, DWORD};
use winapi::um::accctrl::{
    EXPLICIT_ACCESS_A,
    NO_INHERITANCE,
    NO_MULTIPLE_TRUSTEE,
    SET_ACCESS,
    TRUSTEE_A,
    TRUSTEE_IS_GROUP,
    TRUSTEE_IS_SID,
};
use winapi::um::combaseapi::{COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL};
use winapi::um::securitybaseapi::{
    CreateWellKnownSid,
    InitializeSecurityDescriptor,
    GetSidLengthRequired,
};
use winapi::um::winnt::{
    ACL,
    PACL,
    LPSTR,
    SECURITY_DESCRIPTOR_MIN_LENGTH,
    SECURITY_DESCRIPTOR_REVISION,
    SECURITY_MAX_SID_SIZE,
    WinBuiltinAdministratorsSid,
    WinLocalServiceSid,
    WinLocalSystemSid,
    WinNetworkServiceSid,
    WinSelfSid,
};
use winapi::shared::winerror::ERROR_SUCCESS;
use winapi::um::aclapi::SetEntriesInAclA;

fn initialize_com_security() -> bool {
    let mut security_desc: Vec<u8> = Vec::with_capacity(SECURITY_DESCRIPTOR_MIN_LENGTH);
    let mut cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let cd_sid_usize = cd_sid as usize;
    let mut rg_sid_ba: Vec<u8> = Vec::with_capacity(cd_sid_usize);
    let mut rg_sid_ls: Vec<u8> = Vec::with_capacity(cd_sid_usize);
    let mut rg_sid_ns: Vec<u8> = Vec::with_capacity(cd_sid_usize);
    let mut rg_sid_ps: Vec<u8> = Vec::with_capacity(cd_sid_usize);
    let mut rg_sid_sy: Vec<u8> = Vec::with_capacity(cd_sid_usize);
    let mut dw_ret: DWORD = ERROR_SUCCESS;
    let p_acl: *mut PACL = ptr::null_mut();

    let mut fret: bool = false;

    unsafe {
        fret = InitializeSecurityDescriptor(
            security_desc.as_mut_ptr() as LPVOID,
            SECURITY_DESCRIPTOR_REVISION,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    unsafe {
        fret = CreateWellKnownSid(
            WinBuiltinAdministratorsSid,
            ptr::null_mut(),
            rg_sid_ba.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    unsafe {
        fret = CreateWellKnownSid(
            WinLocalServiceSid,
            ptr::null_mut(),
            rg_sid_ls.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    unsafe {
        fret = CreateWellKnownSid(
            WinNetworkServiceSid,
            ptr::null_mut(),
            rg_sid_ns.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    unsafe {
        fret = CreateWellKnownSid(
            WinSelfSid,
            ptr::null_mut(),
            rg_sid_ps.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    unsafe {
        fret = CreateWellKnownSid(
            WinLocalSystemSid,
            ptr::null_mut(),
            rg_sid_sy.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    let mut explicit_access: [EXPLICIT_ACCESS_A; 5] = [
        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ba.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ls.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ns.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ps.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_sy.as_ptr() as LPSTR,
            },
        }
    ];

    unsafe {
        dw_ret = SetEntriesInAclA(
            5,
            explicit_access.as_mut_ptr(),
            ptr::null_mut(),
            p_acl,
        );
    }

    println!("{:?}", dw_ret);

    fret
}

fn main() {
    let _t = initialize_com_security();
    print!("{}", _t);
}

I get the error code here:

println!("{:?}", dw_ret);

Can you help me?

Thank you all and have a nice day

The only difference I see between the C++ code and the Rust code is that you don't reset cd_sid before every invocation of CreateWellKnownSid.

By the way, it would be good form to call Vec::set_len immediately after you've let external code fill the buffers, but in your current program it doesn't really matter.

Hello,

Thank you very much for your answer, I changed it like this but I still have a code 87 in return.

extern crate winapi;

use std::ptr;
use winapi::shared::minwindef::{LPVOID, DWORD};
use winapi::um::accctrl::{
    EXPLICIT_ACCESS_A,
    NO_INHERITANCE,
    NO_MULTIPLE_TRUSTEE,
    SET_ACCESS,
    TRUSTEE_A,
    TRUSTEE_IS_GROUP,
    TRUSTEE_IS_SID,
};
use winapi::um::combaseapi::{COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL};
use winapi::um::securitybaseapi::{
    CreateWellKnownSid,
    InitializeSecurityDescriptor,
    GetSidLengthRequired,
};
use winapi::um::winnt::{
    ACL,
    PACL,
    LPSTR,
    SECURITY_DESCRIPTOR_MIN_LENGTH,
    SECURITY_DESCRIPTOR_REVISION,
    SECURITY_MAX_SID_SIZE,
    WinBuiltinAdministratorsSid,
    WinLocalServiceSid,
    WinLocalSystemSid,
    WinNetworkServiceSid,
    WinSelfSid,
};
use winapi::shared::winerror::ERROR_SUCCESS;
use winapi::um::aclapi::SetEntriesInAclA;
use std::fs::create_dir;

fn initialize_com_security() -> bool {
    let mut security_desc: Vec<u8> = Vec::with_capacity(SECURITY_DESCRIPTOR_MIN_LENGTH);
    let mut dw_ret: DWORD = ERROR_SUCCESS;
    let p_acl: *mut PACL = ptr::null_mut();
    let mut cd_sid: u32 = 0;
    let mut fret: bool = false;

    unsafe {
        fret = InitializeSecurityDescriptor(
            security_desc.as_mut_ptr() as LPVOID,
            SECURITY_DESCRIPTOR_REVISION,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let mut rg_sid_ba: Vec<u8> = Vec::with_capacity(cd_sid as usize);

    unsafe {
        fret = CreateWellKnownSid(
            WinBuiltinAdministratorsSid,
            ptr::null_mut(),
            rg_sid_ba.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let mut rg_sid_ls: Vec<u8> = Vec::with_capacity(cd_sid as usize);

    unsafe {
        fret = CreateWellKnownSid(
            WinLocalServiceSid,
            ptr::null_mut(),
            rg_sid_ls.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let mut rg_sid_ns: Vec<u8> = Vec::with_capacity(cd_sid as usize);

    unsafe {
        fret = CreateWellKnownSid(
            WinNetworkServiceSid,
            ptr::null_mut(),
            rg_sid_ns.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let mut rg_sid_ps: Vec<u8> = Vec::with_capacity(cd_sid as usize);

    unsafe {
        fret = CreateWellKnownSid(
            WinSelfSid,
            ptr::null_mut(),
            rg_sid_ps.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    cd_sid = unsafe { GetSidLengthRequired(8) } as u32;
    let mut rg_sid_sy: Vec<u8> = Vec::with_capacity(cd_sid as usize);

    unsafe {
        fret = CreateWellKnownSid(
            WinLocalSystemSid,
            ptr::null_mut(),
            rg_sid_sy.as_mut_ptr() as *mut _,
            &mut cd_sid,
        ) != 0;
    }

    if fret == false {
        return false;
    }

    let mut explicit_access: [EXPLICIT_ACCESS_A; 5] = [
        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ba.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ls.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ns.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_ps.as_ptr() as LPSTR,
            },
        },

        EXPLICIT_ACCESS_A {
            grfAccessPermissions: COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL,
            grfAccessMode: SET_ACCESS,
            grfInheritance: NO_INHERITANCE,
            Trustee: TRUSTEE_A {
                pMultipleTrustee: ptr::null_mut(),
                MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
                TrusteeForm: TRUSTEE_IS_SID,
                TrusteeType: TRUSTEE_IS_GROUP,
                ptstrName: rg_sid_sy.as_ptr() as LPSTR,
            },
        }
    ];

    unsafe {
        dw_ret = SetEntriesInAclA(
            5,
            explicit_access.as_mut_ptr(),
            ptr::null_mut(),
            p_acl,
        );
    }

    println!("{:?}", dw_ret);

    fret
}

fn main() {
    let _t = initialize_com_security();
    print!("{}", _t);
}