Search code examples
winapirust

Rust Win32 CreateMutexA not working to prevent duplicate application instances


To prevent duplicate application instances from running I create a mutex using CreateMutexA Win32 API call. However, this does not prevent duplicate processes as multiple mutexes with identical names are created. What am I doing wrong?

Code:

use windows::Win32::Foundation::{
    GetLastError,
    ERROR_ALREADY_EXISTS
};
use windows::Win32::System::Threading::{
    CreateMutexA,
};
use windows::core::PCSTR;

pub fn prevent_duplicate() {
    let mutex_key = static_key_as_string!();
    log::info!("Mutex value: {mutex_key}");

    log::info!("Creating Mutex");
    unsafe {
        match CreateMutexA(None, false, PCSTR(mutex_key.as_ptr() as *const u8)) {
            Ok(_) => {
                let error = GetLastError();
                log::error!("{:?} {:?}", error, ERROR_ALREADY_EXISTS);
                if error == ERROR_ALREADY_EXISTS {
                    log::info!("Mutex exists. Exiting");
                    std::process::exit(0)
                }
            },
            Err(_) => {
                log::error!("Could not check existence of Mutext. Continuing");
            },
        };
    }
}

Output proc 1:

[INFO ] Mutex value: P889Z0Hhy2TKEPykDSLuSWdE9bJfNfCsK87aqgNGZ6b09NBIwBh6bwJBj98AkTzO
[INFO ] Creating Mutex
[ERROR] WIN32_ERROR(0) WIN32_ERROR(183)

Output proc 2:

[INFO ] Mutex value: P889Z0Hhy2TKEPykDSLuSWdE9bJfNfCsK87aqgNGZ6b09NBIwBh6bwJBj98AkTzO
[INFO ] Creating Mutex
[ERROR] WIN32_ERROR(0) WIN32_ERROR(183)

EDIT: setting bInitialOwner to true still allows for multiple instances


Solution

  • Check that the string is null-terminated. PCSTR requires your string to have a 0 byte at the end; the default in Rust is that strings are not null-terminated.

    You can include an explicit \0 at the end of the string, but it's probably best to use the windows::core::s! macro, like this example.