mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-10 23:01:14 +03:00
102 lines
2.7 KiB
Rust
102 lines
2.7 KiB
Rust
#![allow(non_snake_case)]
|
|
|
|
use hbb_common::{bail, ResultType};
|
|
use std::{io, ptr::null_mut};
|
|
use winapi::{
|
|
shared::{
|
|
minwindef::{BOOL, DWORD, FALSE, LPBYTE, LPDWORD},
|
|
ntdef::{LPCWSTR, LPWSTR},
|
|
},
|
|
um::winbase::{lstrcmpiW, lstrlenW},
|
|
};
|
|
use windows_strings::PCWSTR;
|
|
|
|
mod driver;
|
|
mod port;
|
|
pub(crate) mod printer;
|
|
pub(crate) mod setup;
|
|
|
|
#[inline]
|
|
pub fn is_rd_printer_installed(app_name: &str) -> ResultType<bool> {
|
|
let printer_name = crate::get_printer_name(app_name);
|
|
let rd_printer_name = PCWSTR::from_raw(printer_name.as_ptr());
|
|
printer::is_printer_added(&rd_printer_name)
|
|
}
|
|
|
|
fn get_wstr_bytes(p: LPWSTR) -> Vec<u16> {
|
|
let mut vec_bytes = vec![];
|
|
unsafe {
|
|
let len: isize = lstrlenW(p) as _;
|
|
if len > 0 {
|
|
for i in 0..len + 1 {
|
|
vec_bytes.push(*p.offset(i));
|
|
}
|
|
}
|
|
}
|
|
vec_bytes
|
|
}
|
|
|
|
fn is_name_equal(name: &PCWSTR, name_from_api: LPCWSTR) -> bool {
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lstrcmpiw
|
|
// For some locales, the lstrcmpi function may be insufficient.
|
|
// If this occurs, use `CompareStringEx` to ensure proper comparison.
|
|
// For example, in Japan call with the NORM_IGNORECASE, NORM_IGNOREKANATYPE, and NORM_IGNOREWIDTH values to achieve the most appropriate non-exact string comparison.
|
|
// Note that specifying these values slows performance, so use them only when necessary.
|
|
//
|
|
// No need to consider `CompareStringEx` for now.
|
|
unsafe { lstrcmpiW(name.as_ptr(), name_from_api) == 0 }
|
|
}
|
|
|
|
fn common_enum<T, R: Sized>(
|
|
enum_name: &str,
|
|
enum_fn: fn(
|
|
Level: DWORD,
|
|
pDriverInfo: LPBYTE,
|
|
cbBuf: DWORD,
|
|
pcbNeeded: LPDWORD,
|
|
pcReturned: LPDWORD,
|
|
) -> BOOL,
|
|
level: DWORD,
|
|
on_data: impl Fn(&T) -> Option<R>,
|
|
on_no_data: impl Fn() -> Option<R>,
|
|
) -> ResultType<Option<R>> {
|
|
let mut needed = 0;
|
|
let mut returned = 0;
|
|
enum_fn(level, null_mut(), 0, &mut needed, &mut returned);
|
|
if needed == 0 {
|
|
return Ok(on_no_data());
|
|
}
|
|
|
|
let mut buffer = vec![0u8; needed as usize];
|
|
if FALSE
|
|
== enum_fn(
|
|
level,
|
|
buffer.as_mut_ptr(),
|
|
needed,
|
|
&mut needed,
|
|
&mut returned,
|
|
)
|
|
{
|
|
bail!(
|
|
"Failed to call {}, error: {}",
|
|
enum_name,
|
|
io::Error::last_os_error()
|
|
)
|
|
}
|
|
|
|
// to-do: how to free the buffers in *const T?
|
|
|
|
let p_enum_info = buffer.as_ptr() as *const T;
|
|
unsafe {
|
|
for i in 0..returned {
|
|
let enum_info = p_enum_info.offset(i as isize);
|
|
let r = on_data(&*enum_info);
|
|
if r.is_some() {
|
|
return Ok(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(on_no_data())
|
|
}
|