#![allow(non_snake_case)]
use crate::co;
use crate::decl::*;
use crate::guard::*;
use crate::kernel::{ffi, privs::*};
pub fn AttachConsole(process: PidParent) -> SysResult<()> {
BoolRet(unsafe { ffi::AttachConsole(process.as_u32()) }).to_sysresult()
}
pub fn CopyFile(existing_file: &str, new_file: &str, fail_if_exists: bool) -> SysResult<()> {
BoolRet(unsafe {
ffi::CopyFileW(
WString::from_str(existing_file).as_ptr(),
WString::from_str(new_file).as_ptr(),
fail_if_exists as _,
)
})
.to_sysresult()
}
pub fn CreateDirectory(
path_name: &str,
security_attributes: Option<&SECURITY_ATTRIBUTES>,
) -> SysResult<()> {
BoolRet(unsafe {
ffi::CreateDirectoryW(
WString::from_str(path_name).as_ptr(),
security_attributes.map_or(std::ptr::null_mut(), |sa| pcvoid(sa)),
)
})
.to_sysresult()
}
#[must_use]
pub fn CreateProcess(
application_name: Option<&str>,
command_line: Option<&str>,
process_attrs: Option<&SECURITY_ATTRIBUTES>,
thread_attrs: Option<&SECURITY_ATTRIBUTES>,
inherit_handles: bool,
creation_flags: co::CREATE,
environment_vars: &[(&str, &str)],
current_dir: Option<&str>,
si: &mut STARTUPINFO,
) -> SysResult<CloseHandlePiGuard> {
let mut buf_cmd_line = WString::from_opt_str(command_line);
let mut pi = PROCESS_INFORMATION::default();
let mut _env_buf = WString::new();
let env_ptr = if environment_vars.is_empty() {
std::ptr::null_mut()
} else {
let env_buf = WString::from_str_vec(
&environment_vars
.iter()
.map(|(name, val)| format!("{}={}", name, val))
.collect::<Vec<_>>(),
);
env_buf.as_ptr() as _
};
unsafe {
BoolRet(ffi::CreateProcessW(
WString::from_opt_str(application_name).as_ptr(),
buf_cmd_line.as_mut_ptr(),
pcvoid_or_null(process_attrs),
pcvoid_or_null(thread_attrs),
inherit_handles as _,
(creation_flags | co::CREATE::UNICODE_ENVIRONMENT).raw(), env_ptr,
WString::from_opt_str(current_dir).as_ptr(),
pvoid(si),
pvoid(&mut pi),
))
.to_sysresult()
.map(|_| CloseHandlePiGuard::new(pi))
}
}
pub fn DeleteFile(file_name: &str) -> SysResult<()> {
BoolRet(unsafe { ffi::DeleteFileW(WString::from_str(file_name).as_ptr()) }).to_sysresult()
}
pub fn ExitProcess(exit_code: u32) {
unsafe { ffi::ExitProcess(exit_code) }
}
pub fn ExitThread(exit_code: u32) {
unsafe { ffi::ExitThread(exit_code) }
}
#[must_use]
pub fn ExpandEnvironmentStrings(src: &str) -> SysResult<String> {
let wsrc = WString::from_str(src);
let mut buf_sz =
match unsafe { ffi::ExpandEnvironmentStringsW(wsrc.as_ptr(), std::ptr::null_mut(), 0) } {
0 => return Err(GetLastError()),
n => n,
};
loop {
let mut buf = WString::new_alloc_buf(buf_sz as _);
let required_sz = match unsafe {
ffi::ExpandEnvironmentStringsW(wsrc.as_ptr(), buf.as_mut_ptr(), buf_sz)
} {
0 => return Err(GetLastError()),
n => n,
};
if required_sz <= buf_sz {
return Ok(buf.to_string());
}
buf_sz = required_sz; }
}
#[must_use]
pub fn FileTimeToSystemTime(ft: &FILETIME) -> SysResult<SYSTEMTIME> {
let mut st = SYSTEMTIME::default();
BoolRet(unsafe { ffi::FileTimeToSystemTime(pcvoid(ft), pvoid(&mut st)) })
.to_sysresult()
.map(|_| st)
}
pub fn FlushProcessWriteBuffers() {
unsafe { ffi::FlushProcessWriteBuffers() }
}
#[must_use]
pub unsafe fn FormatMessage(
flags: co::FORMAT_MESSAGE,
source: Option<*mut std::ffi::c_void>,
message_id: u32,
lang_id: LANGID,
args: &[*mut std::ffi::c_void],
) -> SysResult<String> {
let mut ptr_buf = std::ptr::null_mut::<u16>();
let nchars = match unsafe {
ffi::FormatMessageW(
flags.raw(),
source.unwrap_or(std::ptr::null_mut()),
message_id,
u16::from(lang_id) as _,
&mut ptr_buf as *mut *mut _ as _, 0,
vec_ptr(args) as _,
)
} as _
{
0 => Err(GetLastError()),
nchars => Ok(nchars),
}?;
let final_wstr = WString::from_wchars_count(ptr_buf, nchars as _);
let _ = unsafe { LocalFreeGuard::new(HLOCAL::from_ptr(ptr_buf as _)) }; Ok(final_wstr.to_string())
}
#[must_use]
pub fn GetBinaryType(application_name: &str) -> SysResult<co::SCS> {
let mut binary_type = co::SCS::default();
BoolRet(unsafe {
ffi::GetBinaryTypeW(WString::from_str(application_name).as_ptr(), binary_type.as_mut())
})
.to_sysresult()
.map(|_| binary_type)
}
#[must_use]
pub fn GetCommandLine() -> String {
unsafe { WString::from_wchars_nullt(ffi::GetCommandLineW()) }.to_string()
}
#[must_use]
pub fn GetComputerName() -> SysResult<String> {
let mut buf = WString::new_alloc_buf(MAX_COMPUTERNAME_LENGTH + 1);
let mut sz = buf.buf_len() as u32;
BoolRet(unsafe { ffi::GetComputerNameW(buf.as_mut_ptr(), &mut sz) })
.to_sysresult()
.map(|_| buf.to_string())
}
#[must_use]
pub fn GetCurrentDirectory() -> SysResult<String> {
let mut buf_sz = match unsafe { ffi::GetCurrentDirectoryW(0, std::ptr::null_mut()) } {
0 => return Err(GetLastError()),
n => n,
};
loop {
let mut buf = WString::new_alloc_buf(buf_sz as _);
let returned_chars = match unsafe { ffi::GetCurrentDirectoryW(buf_sz, buf.as_mut_ptr()) } {
0 => return Err(GetLastError()),
n => n,
};
if returned_chars < buf_sz {
return Ok(buf.to_string());
}
buf_sz = returned_chars; }
}
#[must_use]
pub fn GetCurrentProcessId() -> u32 {
unsafe { ffi::GetCurrentProcessId() }
}
#[must_use]
pub fn GetCurrentThreadId() -> u32 {
unsafe { ffi::GetCurrentThreadId() }
}
#[must_use]
pub fn GetDriveType(root_path_name: Option<&str>) -> co::DRIVE {
unsafe {
co::DRIVE::from_raw(ffi::GetDriveTypeW(WString::from_opt_str(root_path_name).as_ptr()))
}
}
pub fn GetDiskFreeSpaceEx(
directory_name: Option<&str>,
free_bytes_available_to_caller: Option<&mut u64>,
total_number_of_bytes: Option<&mut u64>,
total_number_of_free_bytes: Option<&mut u64>,
) -> SysResult<()> {
BoolRet(unsafe {
ffi::GetDiskFreeSpaceExW(
WString::from_opt_str(directory_name).as_ptr(),
free_bytes_available_to_caller.map_or(std::ptr::null_mut(), |n| n),
total_number_of_bytes.map_or(std::ptr::null_mut(), |n| n),
total_number_of_free_bytes.map_or(std::ptr::null_mut(), |n| n),
)
})
.to_sysresult()
}
#[must_use]
pub fn GetDiskSpaceInformation(root_path: &str) -> SysResult<DISK_SPACE_INFORMATION> {
let mut disk_space_info = DISK_SPACE_INFORMATION::default();
match unsafe {
co::ERROR::from_raw(ffi::GetDiskSpaceInformationW(
WString::from_str(root_path).as_ptr(),
pvoid(&mut disk_space_info),
))
} {
co::ERROR::SUCCESS | co::ERROR::MORE_DATA => Ok(disk_space_info),
err => Err(err),
}
}
#[must_use]
pub fn GetEnvironmentStrings() -> SysResult<Vec<(String, String)>> {
PtrRet(unsafe { ffi::GetEnvironmentStringsW() } as _)
.to_sysresult()
.map(|ptr| {
let vec_entries = unsafe { parse_multi_z_str(ptr as _, None) };
unsafe {
ffi::FreeEnvironmentStringsW(ptr);
}
vec_entries
.iter()
.map(|env_str| {
let mut pair = env_str.split("="); let key = pair.next().unwrap();
let val = pair.next().unwrap();
(key.to_owned(), val.to_owned())
})
.collect()
})
}
#[must_use]
pub fn GetFileAttributes(file_name: &str) -> SysResult<co::FILE_ATTRIBUTE> {
const INVALID: u32 = INVALID_FILE_ATTRIBUTES as u32;
match unsafe { ffi::GetFileAttributesW(WString::from_str(file_name).as_ptr()) } {
INVALID => Err(GetLastError()),
flags => Ok(unsafe { co::FILE_ATTRIBUTE::from_raw(flags) }),
}
}
pub fn GetFileAttributesEx(file: &str) -> SysResult<WIN32_FILE_ATTRIBUTE_DATA> {
let mut wfad = WIN32_FILE_ATTRIBUTE_DATA::default();
BoolRet(unsafe {
ffi::GetFileAttributesExW(WString::from_str(file).as_ptr(), 0, pvoid(&mut wfad))
})
.to_sysresult()
.map(|_| wfad)
}
#[must_use]
pub fn GetFirmwareType() -> SysResult<co::FIRMWARE_TYPE> {
let mut ft = co::FIRMWARE_TYPE::default();
BoolRet(unsafe { ffi::GetFirmwareType(ft.as_mut()) })
.to_sysresult()
.map(|_| ft)
}
#[must_use]
pub fn GetLargePageMinimum() -> usize {
unsafe { ffi::GetLargePageMinimum() }
}
#[must_use]
pub fn GetLastError() -> co::ERROR {
unsafe { co::ERROR::from_raw(ffi::GetLastError()) }
}
#[must_use]
pub fn GetLocalTime() -> SYSTEMTIME {
let mut st = SYSTEMTIME::default();
unsafe {
ffi::GetLocalTime(pvoid(&mut st));
}
st
}
#[must_use]
pub fn GetLogicalDrives() -> u32 {
unsafe { ffi::GetLogicalDrives() }
}
#[must_use]
pub fn GetLogicalDriveStrings() -> SysResult<Vec<String>> {
let len = match unsafe { ffi::GetLogicalDriveStringsW(0, std::ptr::null_mut()) } {
0 => Err(GetLastError()),
len => Ok(len),
}?;
let mut buf = WString::new_alloc_buf(len as usize + 1);
unsafe {
BoolRet(ffi::GetLogicalDriveStringsW(len, buf.as_mut_ptr()) as _)
.to_sysresult()
.map(|_| parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())))
}
}
#[must_use]
pub fn GetLongPathName(short_path: &str) -> SysResult<String> {
let short_path_w = WString::from_str(short_path);
let path_sz =
match unsafe { ffi::GetLongPathNameW(short_path_w.as_ptr(), std::ptr::null_mut(), 0) } {
0 => return Err(GetLastError()),
len => len,
};
let mut path_buf = WString::new_alloc_buf(path_sz as _);
match unsafe { ffi::GetLongPathNameW(short_path_w.as_ptr(), path_buf.as_mut_ptr(), path_sz) } {
0 => Err(GetLastError()),
_ => Ok(path_buf.to_string()),
}
}
#[must_use]
pub fn GetNativeSystemInfo() -> SYSTEM_INFO {
let mut si = SYSTEM_INFO::default();
unsafe {
ffi::GetNativeSystemInfo(pvoid(&mut si));
}
si
}
#[must_use]
pub fn GetPrivateProfileSection(
section_name: &str,
file_name: &str,
) -> SysResult<Vec<(String, String)>> {
let mut buf_sz = WString::SSO_LEN; loop {
let mut buf = WString::new_alloc_buf(buf_sz);
let returned_chars = unsafe {
ffi::GetPrivateProfileSectionW(
WString::from_str(section_name).as_ptr(),
buf.as_mut_ptr(),
buf.buf_len() as _,
WString::from_str(file_name).as_ptr(),
)
} + 1 + 1;
if GetLastError() == co::ERROR::FILE_NOT_FOUND {
return Err(co::ERROR::FILE_NOT_FOUND);
} else if (returned_chars as usize) < buf_sz {
return Ok(unsafe { parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())) }
.iter()
.map(|line| match line.split_once('=') {
Some((key, val)) => (key.to_owned(), val.to_owned()),
None => (String::new(), String::new()),
})
.collect());
}
buf_sz *= 2; }
}
#[must_use]
pub fn GetPrivateProfileSectionNames(file_name: Option<&str>) -> SysResult<Vec<String>> {
let mut buf_sz = WString::SSO_LEN; loop {
let mut buf = WString::new_alloc_buf(buf_sz);
let returned_chars = unsafe {
ffi::GetPrivateProfileSectionNamesW(
buf.as_mut_ptr(),
buf.buf_len() as _,
WString::from_opt_str(file_name).as_ptr(),
)
} + 1 + 1;
if GetLastError() == co::ERROR::FILE_NOT_FOUND {
return Err(co::ERROR::FILE_NOT_FOUND);
} else if (returned_chars as usize) < buf_sz {
return Ok(unsafe { parse_multi_z_str(buf.as_ptr(), Some(buf.buf_len())) });
}
buf_sz *= 2; }
}
#[must_use]
pub fn GetPrivateProfileString(
section_name: &str,
key_name: &str,
file_name: &str,
) -> SysResult<Option<String>> {
let mut buf_sz = WString::SSO_LEN; loop {
let mut buf = WString::new_alloc_buf(buf_sz);
unsafe {
ffi::GetPrivateProfileStringW(
WString::from_str(section_name).as_ptr(),
WString::from_str(key_name).as_ptr(),
std::ptr::null_mut(),
buf.as_mut_ptr(),
buf.buf_len() as _,
WString::from_str(file_name).as_ptr(),
);
}
match GetLastError() {
co::ERROR::SUCCESS => {
return Ok(Some(buf.to_string()));
},
co::ERROR::MORE_DATA => {
buf_sz *= 2; },
co::ERROR::FILE_NOT_FOUND => {
return Ok(None);
},
e => {
return Err(e);
},
}
}
}
#[must_use]
pub fn GetStartupInfo<'a, 'b>() -> STARTUPINFO<'a, 'b> {
let mut si = STARTUPINFO::default();
unsafe {
ffi::GetStartupInfoW(pvoid(&mut si));
}
si
}
#[must_use]
pub fn GetSystemDirectory() -> SysResult<String> {
let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
let nchars = match unsafe { ffi::GetSystemDirectoryW(buf.as_mut_ptr(), buf.buf_len() as _) } {
0 => return Err(GetLastError()),
n => n,
} as usize;
if nchars > buf.buf_len() {
buf = WString::new_alloc_buf(nchars);
if unsafe { ffi::GetSystemDirectoryW(buf.as_mut_ptr(), buf.buf_len() as _) } == 0 {
return Err(GetLastError());
}
}
Ok(buf.to_string())
}
#[must_use]
pub fn GetSystemFileCacheSize() -> SysResult<(usize, usize, co::FILE_CACHE)> {
let (mut min, mut max) = (0usize, 0usize);
let mut flags = co::FILE_CACHE::default();
BoolRet(unsafe { ffi::GetSystemFileCacheSize(&mut min, &mut max, flags.as_mut()) })
.to_sysresult()
.map(|_| (min, max, flags))
}
#[must_use]
pub fn GetSystemInfo() -> SYSTEM_INFO {
let mut si = SYSTEM_INFO::default();
unsafe {
ffi::GetSystemInfo(pvoid(&mut si));
}
si
}
#[must_use]
pub fn GetSystemTime() -> SYSTEMTIME {
let mut st = SYSTEMTIME::default();
unsafe {
ffi::GetSystemTime(pvoid(&mut st));
}
st
}
#[must_use]
pub fn GetSystemTimeAsFileTime() -> FILETIME {
let mut ft = FILETIME::default();
unsafe {
ffi::GetSystemTimeAsFileTime(pvoid(&mut ft));
}
ft
}
#[must_use]
pub fn GetSystemTimePreciseAsFileTime() -> FILETIME {
let mut ft = FILETIME::default();
unsafe {
ffi::GetSystemTimePreciseAsFileTime(pvoid(&mut ft));
}
ft
}
#[must_use]
pub fn GetSystemTimes() -> SysResult<(FILETIME, FILETIME, FILETIME)> {
let mut idle_time = FILETIME::default();
let mut kernel_time = FILETIME::default();
let mut user_time = FILETIME::default();
BoolRet(unsafe {
ffi::GetSystemTimes(pvoid(&mut idle_time), pvoid(&mut kernel_time), pvoid(&mut user_time))
})
.to_sysresult()
.map(|_| (idle_time, kernel_time, user_time))
}
#[must_use]
pub fn GetTempFileName(path_name: &str, prefix: &str, unique: u32) -> SysResult<String> {
let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
BoolRet(unsafe {
ffi::GetTempFileNameW(
WString::from_str(path_name).as_ptr(),
WString::from_str(prefix).as_ptr(),
unique,
buf.as_mut_ptr(),
)
} as _)
.to_sysresult()
.map(|_| buf.to_string())
}
#[must_use]
pub fn GetTempPath() -> SysResult<String> {
let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
BoolRet(unsafe { ffi::GetTempPathW(buf.buf_len() as _, buf.as_mut_ptr()) } as _)
.to_sysresult()
.map(|_| buf.to_string())
}
#[must_use]
pub fn GetTickCount64() -> u64 {
unsafe { ffi::GetTickCount64() }
}
pub fn GetVolumeInformation(
root_path_name: Option<&str>,
name: Option<&mut String>,
serial_number: Option<&mut u32>,
max_component_len: Option<&mut u32>,
file_system_flags: Option<&mut co::FILE_VOL>,
file_system_name: Option<&mut String>,
) -> SysResult<()> {
let (mut name_buf, name_buf_sz) = match name {
None => (WString::new(), 0),
Some(_) => (WString::new_alloc_buf(MAX_PATH + 1), MAX_PATH + 1),
};
let (mut sys_name_buf, sys_name_buf_sz) = match file_system_name {
None => (WString::new(), 0),
Some(_) => (WString::new_alloc_buf(MAX_PATH + 1), MAX_PATH + 1),
};
BoolRet(unsafe {
ffi::GetVolumeInformationW(
WString::from_opt_str(root_path_name).as_ptr(),
match name {
Some(_) => name_buf.as_mut_ptr(),
None => std::ptr::null_mut(),
},
name_buf_sz as _,
serial_number.map_or(std::ptr::null_mut(), |n| n),
max_component_len.map_or(std::ptr::null_mut(), |m| m),
file_system_flags.map_or(std::ptr::null_mut(), |f| f.as_mut()),
match file_system_name {
Some(_) => sys_name_buf.as_mut_ptr(),
None => std::ptr::null_mut(),
},
sys_name_buf_sz as _,
)
})
.to_sysresult()
.map(|_| {
if let Some(name) = name {
*name = name_buf.to_string();
}
if let Some(sys_name) = file_system_name {
*sys_name = sys_name_buf.to_string();
}
})
}
#[must_use]
pub fn GetVolumePathName(file_name: &str) -> SysResult<String> {
let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
BoolRet(unsafe {
ffi::GetVolumePathNameW(
WString::from_str(file_name).as_ptr(),
buf.as_mut_ptr(),
buf.buf_len() as _,
)
})
.to_sysresult()
.map(|_| buf.to_string())
}
#[must_use]
pub fn GlobalMemoryStatusEx() -> SysResult<MEMORYSTATUSEX> {
let mut msx = MEMORYSTATUSEX::default();
BoolRet(unsafe { ffi::GlobalMemoryStatusEx(pvoid(&mut msx)) })
.to_sysresult()
.map(|_| msx)
}
#[must_use]
pub const fn HIBYTE(v: u16) -> u8 {
(v >> 8 & 0xff) as _
}
#[must_use]
pub const fn HIDWORD(v: u64) -> u32 {
(v >> 32 & 0xffff_ffff) as _
}
#[must_use]
pub const fn HIWORD(v: u32) -> u16 {
(v >> 16 & 0xffff) as _
}
#[must_use]
pub fn IsDebuggerPresent() -> bool {
unsafe { ffi::IsDebuggerPresent() != 0 }
}
#[must_use]
pub fn IsNativeVhdBoot() -> SysResult<bool> {
let mut is_native = 0;
BoolRet(unsafe { ffi::IsNativeVhdBoot(&mut is_native) })
.to_sysresult()
.map(|_| is_native != 0)
}
#[must_use]
pub fn IsWindows10OrGreater() -> SysResult<bool> {
IsWindowsVersionOrGreater(
HIBYTE(co::WIN32::WINNT_WINTHRESHOLD.raw()) as _,
LOBYTE(co::WIN32::WINNT_WINTHRESHOLD.raw()) as _,
0,
)
}
#[must_use]
pub fn IsWindows7OrGreater() -> SysResult<bool> {
IsWindowsVersionOrGreater(
HIBYTE(co::WIN32::WINNT_WIN7.raw()) as _,
LOBYTE(co::WIN32::WINNT_WIN7.raw()) as _,
0,
)
}
#[must_use]
pub fn IsWindows8OrGreater() -> SysResult<bool> {
IsWindowsVersionOrGreater(
HIBYTE(co::WIN32::WINNT_WIN8.raw()) as _,
LOBYTE(co::WIN32::WINNT_WIN8.raw()) as _,
0,
)
}
#[must_use]
pub fn IsWindows8Point1OrGreater() -> SysResult<bool> {
IsWindowsVersionOrGreater(
HIBYTE(co::WIN32::WINNT_WINBLUE.raw()) as _,
LOBYTE(co::WIN32::WINNT_WINBLUE.raw()) as _,
0,
)
}
#[must_use]
pub fn IsWindowsServer() -> SysResult<bool> {
let mut osvi = OSVERSIONINFOEX::default();
osvi.wProductType = co::VER_NT::WORKSTATION;
let cond_mask = VerSetConditionMask(0, co::VER_MASK::PRODUCT_TYPE, co::VER_COND::EQUAL);
VerifyVersionInfo(&mut osvi, co::VER_MASK::PRODUCT_TYPE, cond_mask).map(|b| !b)
}
#[must_use]
pub fn IsWindowsVersionOrGreater(
major_version: u16,
minor_version: u16,
service_pack_major: u16,
) -> SysResult<bool> {
let mut osvi = OSVERSIONINFOEX::default();
let cond_mask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(0, co::VER_MASK::MAJORVERSION, co::VER_COND::GREATER_EQUAL),
co::VER_MASK::MINORVERSION,
co::VER_COND::GREATER_EQUAL,
),
co::VER_MASK::SERVICEPACKMAJOR,
co::VER_COND::GREATER_EQUAL,
);
osvi.dwMajorVersion = major_version as _;
osvi.dwMinorVersion = minor_version as _;
osvi.wServicePackMajor = service_pack_major;
VerifyVersionInfo(
&mut osvi,
co::VER_MASK::MAJORVERSION | co::VER_MASK::MINORVERSION | co::VER_MASK::SERVICEPACKMAJOR,
cond_mask,
)
}
#[must_use]
pub fn IsWindowsVistaOrGreater() -> SysResult<bool> {
IsWindowsVersionOrGreater(
HIBYTE(co::WIN32::WINNT_VISTA.raw()) as _,
LOBYTE(co::WIN32::WINNT_VISTA.raw()) as _,
0,
)
}
#[must_use]
pub const fn LOBYTE(v: u16) -> u8 {
(v & 0xff) as _
}
#[must_use]
pub const fn LODWORD(v: u64) -> u32 {
(v & 0xffff_ffff) as _
}
#[must_use]
pub const fn LOWORD(v: u32) -> u16 {
(v & 0xffff) as _
}
#[must_use]
pub const fn MAKEDWORD(lo: u16, hi: u16) -> u32 {
((lo as u32 & 0xffff) | ((hi as u32 & 0xffff) << 16)) as _
}
#[must_use]
pub const fn MAKEQWORD(lo: u32, hi: u32) -> u64 {
((lo as u64 & 0xffff_ffff) | ((hi as u64 & 0xffff_ffff) << 32)) as _
}
#[must_use]
pub const fn MAKEWORD(lo: u8, hi: u8) -> u16 {
(lo as u16 & 0xff) | ((hi as u16 & 0xff) << 8) as u16
}
pub fn MoveFile(existing_file: &str, new_file: &str) -> SysResult<()> {
BoolRet(unsafe {
ffi::MoveFileW(
WString::from_str(existing_file).as_ptr(),
WString::from_str(new_file).as_ptr(),
)
})
.to_sysresult()
}
pub fn MoveFileEx(
existing_file: &str,
new_file: Option<&str>,
flags: co::MOVEFILE,
) -> SysResult<()> {
BoolRet(unsafe {
ffi::MoveFileExW(
WString::from_str(existing_file).as_ptr(),
WString::from_opt_str(new_file).as_ptr(),
flags.raw(),
)
})
.to_sysresult()
}
#[must_use]
pub fn MulDiv(number: i32, numerator: i32, denominator: i32) -> i32 {
unsafe { ffi::MulDiv(number, numerator, denominator) }
}
#[must_use]
pub fn MultiByteToWideChar(
code_page: co::CP,
flags: co::MBC,
multi_byte_str: &[u8],
) -> SysResult<Vec<u16>> {
let num_bytes = match unsafe {
ffi::MultiByteToWideChar(
code_page.raw() as _,
flags.raw(),
vec_ptr(multi_byte_str),
multi_byte_str.len() as _,
std::ptr::null_mut(),
0,
)
} {
0 => Err(GetLastError()),
num_bytes => Ok(num_bytes),
}?;
let mut buf = vec![0u16; num_bytes as _];
BoolRet(unsafe {
ffi::MultiByteToWideChar(
code_page.raw() as _,
flags.raw(),
vec_ptr(multi_byte_str),
multi_byte_str.len() as _,
buf.as_mut_ptr(),
num_bytes as _,
)
})
.to_sysresult()
.map(|_| buf)
}
pub fn OutputDebugString(output_string: &str) {
unsafe { ffi::OutputDebugStringW(WString::from_str(output_string).as_ptr()) }
}
#[must_use]
pub fn QueryPerformanceCounter() -> SysResult<i64> {
let mut perf_count = 0i64;
BoolRet(unsafe { ffi::QueryPerformanceCounter(&mut perf_count) })
.to_sysresult()
.map(|_| perf_count)
}
#[must_use]
pub fn QueryPerformanceFrequency() -> SysResult<i64> {
let mut freq = 0i64;
BoolRet(unsafe { ffi::QueryPerformanceFrequency(&mut freq) })
.to_sysresult()
.map(|_| freq)
}
#[must_use]
pub fn QueryUnbiasedInterruptTime() -> SysResult<u64> {
let mut t = 0u64;
BoolRet(unsafe { ffi::QueryUnbiasedInterruptTime(&mut t) })
.to_sysresult()
.map(|_| t)
}
pub fn ReplaceFile(
replaced: &str,
replacement: &str,
backup: Option<&str>,
flags: co::REPLACEFILE,
) -> SysResult<()> {
BoolRet(unsafe {
ffi::ReplaceFileW(
WString::from_str(replaced).as_ptr(),
WString::from_str(replacement).as_ptr(),
WString::from_opt_str(backup).as_ptr(),
flags.raw(),
std::ptr::null_mut(),
std::ptr::null_mut(),
)
})
.to_sysresult()
}
pub fn SetCurrentDirectory(path_name: &str) -> SysResult<()> {
BoolRet(unsafe { ffi::SetCurrentDirectoryW(WString::from_str(path_name).as_ptr()) })
.to_sysresult()
}
pub fn SetFileAttributes(file_name: &str, attributes: co::FILE_ATTRIBUTE) -> SysResult<()> {
BoolRet(unsafe {
ffi::SetFileAttributesW(WString::from_str(file_name).as_ptr(), attributes.raw())
})
.to_sysresult()
}
pub fn SetLastError(err_code: co::ERROR) {
unsafe { ffi::SetLastError(err_code.raw()) }
}
pub fn SetThreadStackGuarantee(stack_size_in_bytes: u32) -> SysResult<u32> {
let mut sz = stack_size_in_bytes;
BoolRet(unsafe { ffi::SetThreadStackGuarantee(&mut sz) })
.to_sysresult()
.map(|_| sz)
}
pub fn Sleep(milliseconds: u32) {
unsafe { ffi::Sleep(milliseconds) }
}
pub fn SwitchToThread() -> SysResult<()> {
BoolRet(unsafe { ffi::SwitchToThread() }).to_sysresult()
}
#[must_use]
pub fn SystemTimeToFileTime(st: &SYSTEMTIME) -> SysResult<FILETIME> {
let mut ft = FILETIME::default();
BoolRet(unsafe { ffi::SystemTimeToFileTime(pcvoid(st), pvoid(&mut ft)) })
.to_sysresult()
.map(|_| ft)
}
#[must_use]
pub fn SystemTimeToTzSpecificLocalTime(
time_zone: Option<&TIME_ZONE_INFORMATION>,
universal_time: &SYSTEMTIME,
) -> SysResult<SYSTEMTIME> {
let mut local_time = SYSTEMTIME::default();
BoolRet(unsafe {
ffi::SystemTimeToTzSpecificLocalTime(
time_zone.map_or(std::ptr::null(), |lp| pcvoid(lp)),
pcvoid(universal_time),
pvoid(&mut local_time),
)
})
.to_sysresult()
.map(|_| local_time)
}
#[must_use]
pub fn VerifyVersionInfo(
osvix: &mut OSVERSIONINFOEX,
type_mask: co::VER_MASK,
condition_mask: u64,
) -> SysResult<bool> {
match unsafe { ffi::VerifyVersionInfoW(pvoid(osvix), type_mask.raw(), condition_mask) } {
0 => match GetLastError() {
co::ERROR::OLD_WIN_VERSION => Ok(false),
err => Err(err),
},
_ => Ok(true),
}
}
#[must_use]
pub fn VerSetConditionMask(
condition_mask: u64,
type_mask: co::VER_MASK,
condition: co::VER_COND,
) -> u64 {
unsafe { ffi::VerSetConditionMask(condition_mask, type_mask.raw(), condition.raw()) }
}
#[must_use]
pub fn WideCharToMultiByte(
code_page: co::CP,
flags: co::WC,
wide_char_str: &[u16],
default_char: Option<u8>,
used_default_char: Option<&mut bool>,
) -> SysResult<Vec<u8>> {
let mut default_char_buf = default_char.unwrap_or_default();
let num_bytes = match unsafe {
ffi::WideCharToMultiByte(
code_page.raw() as _,
flags.raw(),
vec_ptr(wide_char_str),
wide_char_str.len() as _,
std::ptr::null_mut(),
0,
&mut default_char_buf,
std::ptr::null_mut(),
)
} {
0 => Err(GetLastError()),
num_bytes => Ok(num_bytes),
}?;
let mut u8_buf = vec![0u8; num_bytes as _];
let mut bool_buf = 0;
BoolRet(unsafe {
ffi::WideCharToMultiByte(
code_page.raw() as _,
flags.raw(),
vec_ptr(wide_char_str),
wide_char_str.len() as _,
u8_buf.as_mut_ptr() as _,
num_bytes as _,
&mut default_char_buf,
&mut bool_buf,
)
})
.to_sysresult()
.map(|_| {
if let Some(used_default_char) = used_default_char {
*used_default_char = bool_buf != 0;
}
u8_buf
})
}
pub fn WritePrivateProfileString(
section_name: &str,
key_name: Option<&str>,
new_val: Option<&str>,
file_name: &str,
) -> SysResult<()> {
BoolRet(unsafe {
ffi::WritePrivateProfileStringW(
WString::from_str(section_name).as_ptr(),
WString::from_opt_str(key_name).as_ptr(),
WString::from_opt_str(new_val).as_ptr(),
WString::from_str(file_name).as_ptr(),
)
})
.to_sysresult()
}