To add to the solution suggested by @user7860670, i.e: checking the registry key AppsUseLightTheme, I think it is worth having some code example.
To read from the registry Win32 has RegGetValue.
C++
bool is_light_theme() {
    // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
    // The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian
    auto buffer = std::vector<char>(4);
    auto cbData = static_cast<DWORD>(buffer.size() * sizeof(char));
    auto res = RegGetValueW(
        HKEY_CURRENT_USER,
        L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
        L"AppsUseLightTheme",
        RRF_RT_REG_DWORD, // expected value type
        nullptr,
        buffer.data(),
        &cbData);
    if (res != ERROR_SUCCESS) {
        throw std::runtime_error("Error: error_code=" + std::to_string(res));
    }
    // convert bytes written to our buffer to an int, assuming little-endian
    auto i = int(buffer[3] << 24 |
        buffer[2] << 16 |
        buffer[1] << 8 |
        buffer[0]);
    return i == 1;
}
Rust
Using the windows-rs projection crate:
pub fn is_light_theme() -> bool {
    // based on https://stackoverflow.com/a/51336913/709884
    let mut buffer: [u8; 4] = [0; 4];
    let mut cb_data: u32 = (buffer.len()).try_into().unwrap();
    let res = unsafe {
        RegGetValueW(
            HKEY_CURRENT_USER,
            r#"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"#
                .to_wide()
                .as_pwstr(),
            "AppsUseLightTheme".to_wide().as_pwstr(),
            RRF_RT_REG_DWORD,
            std::ptr::null_mut(),
            buffer.as_mut_ptr() as _,
            &mut cb_data as *mut _,
        )
    };
    assert_eq!(
        res,
        ERROR_SUCCESS,
        format!("failed to read key from registry: err_code={}", res).as_str(),
    );
    // REG_DWORD is signed 32-bit, using little endian
    let light_mode = i32::from_le_bytes(buffer) == 1;
    light_mode
}
pub fn is_dark_theme() -> bool {
    !is_light_theme()
}
// convert &str to Win32 PWSTR
#[derive(Default)]
pub struct WideString(pub Vec<u16>);
pub trait ToWide {
    fn to_wide(&self) -> WideString;
}
impl ToWide for &str {
    fn to_wide(&self) -> WideString {
        let mut result: Vec<u16> = self.encode_utf16().collect();
        result.push(0);
        WideString(result)
    }
}
impl ToWide for String {
    fn to_wide(&self) -> WideString {
        let mut result: Vec<u16> = self.encode_utf16().collect();
        result.push(0);
        WideString(result)
    }
}
impl WideString {
    pub fn as_pwstr(&self) -> PWSTR {
        PWSTR(self.0.as_ptr() as *mut _)
    }
}