use std::{path::PathBuf, slice};
use widestring::{U16CStr, U16CString};
use windows::Win32::Storage::CloudFilters::{CF_CALLBACK_INFO, CF_PROCESS_INFO};
use crate::placeholder::Placeholder;
pub type RawConnectionKey = i64;
pub type RawTransferKey = i64;
#[derive(Debug)]
pub struct Request(CF_CALLBACK_INFO);
impl Request {
pub(crate) fn new(info: CF_CALLBACK_INFO) -> Self {
Self(info)
}
pub fn connection_key(&self) -> RawConnectionKey {
self.0.ConnectionKey.0
}
pub fn transfer_key(&self) -> RawTransferKey {
self.0.TransferKey
}
pub fn volume_guid_path(&self) -> &U16CStr {
unsafe { U16CStr::from_ptr_str(self.0.VolumeGuidName.0) }
}
pub fn volume_letter(&self) -> &U16CStr {
unsafe { U16CStr::from_ptr_str(self.0.VolumeDosName.0) }
}
pub fn volume_serial_number(&self) -> u32 {
self.0.VolumeSerialNumber
}
pub fn process(&self) -> Process {
Process(unsafe { *self.0.ProcessInfo })
}
pub fn sync_root_file_id(&self) -> i64 {
self.0.SyncRootFileId
}
pub fn file_id(&self) -> i64 {
self.0.FileId
}
pub fn file_size(&self) -> u64 {
self.0.FileSize as u64
}
pub fn path(&self) -> PathBuf {
let mut path =
PathBuf::from(unsafe { U16CStr::from_ptr_str(self.0.VolumeDosName.0) }.to_os_string());
path.push(unsafe { U16CStr::from_ptr_str(self.0.NormalizedPath.0) }.to_os_string());
path
}
pub fn priority_hint(&self) -> u8 {
self.0.PriorityHint
}
pub fn file_blob(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self.0.FileIdentity as *mut u8,
self.0.FileIdentityLength as usize,
)
}
}
pub fn register_blob(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self.0.SyncRootIdentity as *mut u8,
self.0.SyncRootIdentityLength as usize,
)
}
}
pub fn placeholder(&self) -> Placeholder {
Placeholder::new(
self.connection_key(),
self.transfer_key(),
self.path(),
self.file_size(),
)
}
pub fn reset_timeout() {}
}
#[derive(Debug)]
pub struct Process(CF_PROCESS_INFO);
impl Process {
pub fn name(&self) -> &U16CStr {
unsafe { U16CStr::from_ptr_str(self.0.PackageName.0) }
}
pub fn id(&self) -> u32 {
self.0.ProcessId
}
pub fn session_id(&self) -> u32 {
self.0.SessionId
}
pub fn application_id(&self) -> &U16CStr {
unsafe { U16CStr::from_ptr_str(self.0.ApplicationId.0) }
}
pub fn command_line(&self) -> &U16CStr {
unsafe { U16CStr::from_ptr_str(self.0.CommandLine.0) }
}
pub fn path(&self) -> Option<PathBuf> {
let path = unsafe { U16CString::from_ptr_str(self.0.ImagePath.0) };
if path == unsafe { U16CString::from_str_unchecked("UNKNOWN") } {
None
} else {
Some(path.to_os_string().into())
}
}
}