#![allow(clippy::missing_errors_doc)]
use windows::core::{HRESULT, HSTRING};
use windows::Win32::System::HostComputeSystem::{
HcsCreateComputeSystem, HcsGetComputeSystemProperties, HcsModifyComputeSystem,
HcsOpenComputeSystem, HcsPauseComputeSystem, HcsResumeComputeSystem, HcsSaveComputeSystem,
HcsShutDownComputeSystem, HcsStartComputeSystem, HcsTerminateComputeSystem, HCS_SYSTEM,
};
use crate::error::{HcsError, HcsResult};
use crate::handle::{OwnedSystem, SendHandle};
use crate::operation::run_operation;
const HR_OK: HRESULT = HRESULT(0);
#[inline]
fn to_hresult(result: windows::core::Result<()>) -> HRESULT {
match result {
Ok(()) => HR_OK,
Err(e) => e.code(),
}
}
#[derive(Debug)]
pub struct ComputeSystem {
inner: OwnedSystem,
}
impl ComputeSystem {
pub async fn create(id: &str, configuration_json: &str) -> HcsResult<Self> {
let id_w = HSTRING::from(id);
let cfg_w = HSTRING::from(configuration_json);
let mut handle_slot: Option<SendHandle<HCS_SYSTEM>> = None;
let result = {
let handle_slot = &mut handle_slot;
run_operation(move |op| {
let res = unsafe { HcsCreateComputeSystem(&id_w, &cfg_w, op, None) };
match res {
Ok(sys) => {
*handle_slot = Some(SendHandle(sys));
HR_OK
}
Err(e) => e.code(),
}
})
.await
};
let _json = result?;
let Some(raw) = handle_slot else {
return Err(HcsError::Other {
hresult: 0,
message: "HcsCreateComputeSystem returned success without a handle".to_string(),
});
};
if raw.0.is_invalid() {
return Err(HcsError::Other {
hresult: 0,
message: "HcsCreateComputeSystem returned an invalid handle".to_string(),
});
}
let inner = unsafe { OwnedSystem::from_raw(raw.0) };
Ok(Self { inner })
}
pub fn open(id: &str, requested_access: u32) -> HcsResult<Self> {
let id_w = HSTRING::from(id);
let raw = unsafe { HcsOpenComputeSystem(&id_w, requested_access) }
.map_err(|e| HcsError::from_hresult(e.code(), format!("HcsOpenComputeSystem({id})")))?;
if raw.is_invalid() {
return Err(HcsError::Other {
hresult: 0,
message: "HcsOpenComputeSystem returned an invalid handle".to_string(),
});
}
let inner = unsafe { OwnedSystem::from_raw(raw) };
Ok(Self { inner })
}
#[must_use]
pub fn raw(&self) -> SendHandle<HCS_SYSTEM> {
self.inner.as_raw()
}
pub async fn start(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsStartComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn shutdown(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsShutDownComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn terminate(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsTerminateComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn pause(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsPauseComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn resume(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsResumeComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn save(&self, options_json: &str) -> HcsResult<()> {
let opts_w = HSTRING::from(options_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsSaveComputeSystem(*handle, op, &opts_w) })
})
.await?;
Ok(())
}
pub async fn properties(&self, property_query_json: &str) -> HcsResult<String> {
let query_w = HSTRING::from(property_query_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsGetComputeSystemProperties(*handle, op, &query_w) })
})
.await
}
pub async fn modify(&self, modification_json: &str) -> HcsResult<()> {
let mod_w = HSTRING::from(modification_json);
let handle = self.inner.as_raw();
run_operation(move |op| {
to_hresult(unsafe { HcsModifyComputeSystem(*handle, op, &mod_w, None) })
})
.await?;
Ok(())
}
}