use crate::*;
use abistr::*;
use winapi::ctypes::c_char;
use winapi::shared::minwindef::{FALSE, LPARAM, BOOL, TRUE};
use winapi::shared::ntdef::HANDLE;
use winapi::shared::winerror::*;
use winapi::um::errhandlingapi::SetLastError;
use winapi::um::handleapi::DuplicateHandle;
use winapi::um::winnt::DUPLICATE_SAME_ACCESS;
use winapi::um::winuser::*;
use core::ptr::null;
pub fn create_window_station_a(
winsta: impl TryIntoAsOptCStr,
flags: impl Into<winsta::CreateWindowFlags>,
desired_access: impl Into<winsta::AccessRights>,
sa: Option<&security::Attributes>,
) -> Result<winsta::OwnedHandle, Error> {
let handle = unsafe { CreateWindowStationA(
winsta.try_into().map_err(|_| Error(E_STRING_NOT_NULL_TERMINATED as _))?.as_opt_cstr(),
flags.into().into(),
desired_access.into().into(),
sa.map_or(null(), |sa| sa) as *mut _
)};
Error::get_last_if(handle.is_null())?;
unsafe { winsta::OwnedHandle::from_raw(handle) }
}
pub fn create_window_station_w(
winsta: impl TryIntoAsOptCStr<u16>,
flags: impl Into<winsta::CreateWindowFlags>,
desired_access: impl Into<winsta::AccessRights>,
sa: Option<&security::Attributes>,
) -> Result<winsta::OwnedHandle, Error> {
let handle = unsafe { CreateWindowStationW(
winsta.try_into().map_err(|_| Error(E_STRING_NOT_NULL_TERMINATED as _))?.as_opt_cstr(),
flags.into().into(),
desired_access.into().into(),
sa.map_or(null(), |sa| sa) as *mut _
)};
Error::get_last_if(handle.is_null())?;
unsafe { winsta::OwnedHandle::from_raw(handle) }
}
pub fn enum_window_stations_a<F: FnMut(CStrPtr) -> Result<(), Error>>(mut enum_func: F) -> Result<(), Error> {
let enum_func : *mut F = &mut enum_func;
Error::get_last_if(FALSE == unsafe { EnumWindowStationsA(Some(fwd_enum_window_stations_a::<F>), enum_func as LPARAM) })
}
unsafe extern "system" fn fwd_enum_window_stations_a<F: FnMut(CStrPtr) -> Result<(), Error>>(winsta: *mut c_char, param: LPARAM) -> BOOL {
let winsta = unsafe { CStrPtr::from_ptr_unbounded(winsta) };
let f = unsafe { &mut *(param as *mut F) };
match f(winsta) {
Ok(()) => TRUE,
Err(e) => {
unsafe { SetLastError(e.0) };
FALSE
},
}
}
pub fn enum_window_stations_w<F: FnMut(CStrPtr<u16>) -> Result<(), Error>>(mut enum_func: F) -> Result<(), Error> {
let enum_func : *mut F = &mut enum_func;
Error::get_last_if(FALSE == unsafe { EnumWindowStationsW(Some(fwd_enum_window_stations_w::<F>), enum_func as LPARAM) })
}
unsafe extern "system" fn fwd_enum_window_stations_w<F: FnMut(CStrPtr<u16>) -> Result<(), Error>>(winsta: *mut u16, param: LPARAM) -> BOOL {
let winsta = unsafe { CStrPtr::<u16>::from_ptr_unbounded(winsta) };
let f = unsafe { &mut *(param as *mut F) };
match f(winsta) {
Ok(()) => TRUE,
Err(e) => {
unsafe { SetLastError(e.0) };
FALSE
},
}
}
pub fn open_process_window_station() -> Result<winsta::OwnedHandle, Error> {
let mut winsta : HANDLE = unsafe { GetProcessWindowStation() }.cast();
Error::get_last_if(winsta.is_null())?;
let process = get_current_process().as_handle();
Error::get_last_if(FALSE == unsafe { DuplicateHandle(process, winsta, process, &mut winsta, 0, 0, DUPLICATE_SAME_ACCESS) })?;
unsafe { winsta::OwnedHandle::from_raw(winsta.cast()) }
}
pub fn open_window_station_a(
winsta: impl TryIntoAsCStr,
inherit: bool,
desired_access: impl Into<winsta::AccessRights>,
) -> Result<winsta::OwnedHandle, Error> {
let handle = unsafe { OpenWindowStationA(
winsta.try_into().map_err(|_| Error(E_STRING_NOT_NULL_TERMINATED as _))?.as_cstr(),
inherit as _,
desired_access.into().into()
)};
Error::get_last_if(handle.is_null())?;
unsafe { winsta::OwnedHandle::from_raw(handle) }
}
pub fn open_window_station_w(
winsta: impl TryIntoAsCStr<u16>,
inherit: bool,
desired_access: impl Into<winsta::AccessRights>,
) -> Result<winsta::OwnedHandle, Error> {
let handle = unsafe { OpenWindowStationW(
winsta.try_into().map_err(|_| Error(E_STRING_NOT_NULL_TERMINATED as _))?.as_cstr(),
inherit as _,
desired_access.into().into()
)};
Error::get_last_if(handle.is_null())?;
unsafe { winsta::OwnedHandle::from_raw(handle) }
}
pub fn set_process_window_station(winsta: &winsta::OwnedHandle) -> Result<(), Error> {
Error::get_last_if(FALSE == unsafe { SetProcessWindowStation(winsta.as_handle()) })
}