-
Notifications
You must be signed in to change notification settings - Fork 1
Transform the bin into a lib #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
ada9525
Transform the bin in a lib
yozhgoor 585cd8e
WIP
yozhgoor 55c90c4
Modify errors messages
yozhgoor 5b9fc15
formatting
yozhgoor 0d0bb47
Merge branch 'main' into lib
yozhgoor 78acca9
Clean up
yozhgoor e5235c9
Remove main.rs
yozhgoor 493648b
Add arguments to the new function and remove create_process
yozhgoor 0597c31
Attempt to use an Option for the `current_directory` argument
yozhgoor f0cf958
Clean up
yozhgoor ec3d73d
Looks good
yozhgoor 844d3a3
Listen to the Clippy
yozhgoor 240f438
Add ExitCode
yozhgoor 6238a18
Remove duplicate
yozhgoor 268c4d1
Better naming
yozhgoor 03522fe
Initialize memory for startup_info
yozhgoor c933559
Better naming
yozhgoor dd34f5c
After review
yozhgoor 1c014f4
Create a variable for the process_creation_flags
yozhgoor 2663ea7
Fix error in main workflow
yozhgoor d94b5b9
Use thiserror for the Error type of the Result
yozhgoor b689041
Use a path instead of a &str for the current_directory argument
yozhgoor 050f91e
Remove the close_handle function since it's not duplicate code anymore
yozhgoor e1c520b
Use ExitStatus instead of StatusCode
yozhgoor 9c1e1c7
Remove the command function
yozhgoor 7a8a470
Attempt to add a `try_wait` function
yozhgoor 0004d52
Use a match instead of if else
yozhgoor bd139ab
Use GetExitCodeProcess in try_wait
yozhgoor 6a36a7a
Modify the wait function to return an exit code
yozhgoor 3da034b
Clean up
yozhgoor f30270b
Better error handling
yozhgoor 9f8c1cc
Get the error code instead of formatting it into a string
yozhgoor 4b48d31
fmt
yozhgoor afbfef4
Add a Command struct to create process
yozhgoor a24a798
After review
yozhgoor 574435f
Oops
yozhgoor 048337d
Add comment about the allowed lint `non_snake_case`
yozhgoor 5eca5fd
After review
yozhgoor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,199 @@ | ||
// Disable warning for the crate name, not a really good way to do this but.. | ||
// (https://github.com/rust-lang/rust/issues/45127) | ||
#![allow(non_snake_case)] | ||
|
||
use std::ffi::{c_void, OsStr, OsString}; | ||
use std::mem::size_of; | ||
use std::path::{Path, PathBuf}; | ||
use thiserror::Error; | ||
use windows::Win32::Foundation::{CloseHandle, GetLastError, PWSTR, STATUS_PENDING}; | ||
use windows::Win32::Security::SECURITY_ATTRIBUTES; | ||
use windows::Win32::System::Threading::{ | ||
GetExitCodeProcess, TerminateProcess, WaitForSingleObject, PROCESS_CREATION_FLAGS, | ||
PROCESS_INFORMATION, STARTUPINFOW, WAIT_OBJECT_0, | ||
}; | ||
use windows::Win32::System::WindowsProgramming::INFINITE; | ||
|
||
#[derive(Error, Debug)] | ||
pub enum Error { | ||
#[error("cannot create process: {0}")] | ||
CreationFailed(u32), | ||
#[error("cannot get exit status: {0}")] | ||
GetExitCodeFailed(u32), | ||
#[error("cannot kill process: {0}")] | ||
KillFailed(u32), | ||
} | ||
|
||
type Result<T> = std::result::Result<T, Error>; | ||
|
||
#[derive(Debug)] | ||
pub struct Command { | ||
command: OsString, | ||
inherit_handles: bool, | ||
current_directory: Option<PathBuf>, | ||
} | ||
|
||
impl Command { | ||
pub fn new(command: impl Into<OsString>) -> Self { | ||
Self { | ||
command: command.into(), | ||
inherit_handles: true, | ||
current_directory: None, | ||
} | ||
} | ||
|
||
pub fn inherit_handles(&mut self, inherit: bool) -> &mut Self { | ||
self.inherit_handles = inherit; | ||
self | ||
} | ||
|
||
pub fn current_dir(&mut self, dir: impl Into<PathBuf>) -> &mut Self { | ||
self.current_directory = Some(dir.into()); | ||
self | ||
} | ||
|
||
pub fn spawn(&mut self) -> Result<Child> { | ||
Child::new( | ||
&self.command, | ||
self.inherit_handles, | ||
self.current_directory.as_deref(), | ||
) | ||
} | ||
|
||
pub fn status(&mut self) -> Result<ExitStatus> { | ||
self.spawn()?.wait() | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct Child { | ||
process_information: PROCESS_INFORMATION, | ||
} | ||
|
||
impl Child { | ||
fn new( | ||
command: &OsStr, | ||
inherit_handles: bool, | ||
current_directory: Option<&Path>, | ||
) -> Result<Self> { | ||
let mut startup_info = STARTUPINFOW::default(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would start unsafe here in the beginning as the entire logic is one block here |
||
let mut process_info = PROCESS_INFORMATION::default(); | ||
|
||
startup_info.cb = size_of::<STARTUPINFOW>() as u32; | ||
|
||
let process_creation_flags = PROCESS_CREATION_FLAGS(0); | ||
|
||
let res = unsafe { | ||
if let Some(directory) = current_directory { | ||
let directory = directory.as_os_str(); | ||
windows::Win32::System::Threading::CreateProcessW( | ||
PWSTR::default(), | ||
command, | ||
std::ptr::null() as *const SECURITY_ATTRIBUTES, | ||
std::ptr::null() as *const SECURITY_ATTRIBUTES, | ||
inherit_handles, | ||
process_creation_flags, | ||
std::ptr::null() as *const c_void, | ||
directory, | ||
&startup_info, | ||
&mut process_info as *mut PROCESS_INFORMATION, | ||
) | ||
} else { | ||
windows::Win32::System::Threading::CreateProcessW( | ||
PWSTR::default(), | ||
command, | ||
std::ptr::null() as *const SECURITY_ATTRIBUTES, | ||
std::ptr::null() as *const SECURITY_ATTRIBUTES, | ||
inherit_handles, | ||
process_creation_flags, | ||
std::ptr::null() as *const c_void, | ||
PWSTR::default(), | ||
&startup_info, | ||
&mut process_info as *mut PROCESS_INFORMATION, | ||
) | ||
} | ||
}; | ||
|
||
if res.as_bool() { | ||
Ok(Self { | ||
process_information: process_info, | ||
}) | ||
} else { | ||
Err(Error::CreationFailed(unsafe { GetLastError().0 })) | ||
} | ||
} | ||
|
||
pub fn wait(&self) -> Result<ExitStatus> { | ||
unsafe { | ||
let mut exit_code: u32 = 0; | ||
let res = WaitForSingleObject(self.process_information.hProcess, INFINITE); | ||
|
||
if res == WAIT_OBJECT_0 { | ||
if GetExitCodeProcess( | ||
self.process_information.hProcess, | ||
&mut exit_code as *mut u32, | ||
) | ||
.as_bool() | ||
{ | ||
close_handles(&self.process_information); | ||
Ok(ExitStatus(exit_code)) | ||
} else { | ||
Err(Error::GetExitCodeFailed(GetLastError().0)) | ||
} | ||
} else { | ||
Err(Error::GetExitCodeFailed(GetLastError().0)) | ||
} | ||
} | ||
} | ||
|
||
pub fn try_wait(&self) -> Result<Option<ExitStatus>> { | ||
unsafe { | ||
let mut exit_code: u32 = 0; | ||
|
||
let res = GetExitCodeProcess( | ||
self.process_information.hProcess, | ||
&mut exit_code as *mut u32, | ||
); | ||
|
||
if res.as_bool() { | ||
if exit_code == STATUS_PENDING.0 { | ||
Ok(None) | ||
} else { | ||
close_handles(&self.process_information); | ||
Ok(Some(ExitStatus(exit_code))) | ||
} | ||
} else { | ||
Err(Error::GetExitCodeFailed(GetLastError().0)) | ||
} | ||
} | ||
} | ||
|
||
pub fn kill(&self) -> Result<()> { | ||
unsafe { | ||
let res = TerminateProcess(self.process_information.hProcess, 0); | ||
|
||
if res.as_bool() { | ||
Ok(()) | ||
} else { | ||
Err(Error::KillFailed(GetLastError().0)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub struct ExitStatus(u32); | ||
|
||
impl ExitStatus { | ||
pub fn success(&self) -> bool { | ||
self.0 == 0 | ||
} | ||
|
||
pub fn code(&self) -> u32 { | ||
self.0 | ||
} | ||
} | ||
|
||
unsafe fn close_handles(process_info: &PROCESS_INFORMATION) { | ||
CloseHandle(process_info.hProcess); | ||
CloseHandle(process_info.hThread); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.