mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 10:13:13 +02:00
Rust 1.85, edition=2024 (#15741)
This commit is contained in:
@ -4,7 +4,7 @@ description = "Nushell system querying"
|
||||
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-system"
|
||||
name = "nu-system"
|
||||
version = "0.104.1"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@ -48,4 +48,4 @@ windows = { workspace = true, features = [
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_System_Threading",
|
||||
"Win32_UI_Shell",
|
||||
]}
|
||||
]}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::{atomic::AtomicU32, Arc};
|
||||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
|
||||
use std::io;
|
||||
|
||||
@ -274,11 +274,7 @@ impl ForegroundGuard {
|
||||
} else if pcnt
|
||||
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |count| {
|
||||
// Avoid a race condition: only increment if count is > 0
|
||||
if count > 0 {
|
||||
Some(count + 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if count > 0 { Some(count + 1) } else { None }
|
||||
})
|
||||
.is_ok()
|
||||
{
|
||||
@ -349,7 +345,7 @@ impl Drop for ForegroundGuard {
|
||||
#[cfg(unix)]
|
||||
mod child_pgroup {
|
||||
use nix::{
|
||||
sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal},
|
||||
sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction},
|
||||
unistd::{self, Pid},
|
||||
};
|
||||
use std::{
|
||||
|
@ -1,7 +1,7 @@
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use libc::{
|
||||
c_char, kinfo_proc, sysctl, CTL_HW, CTL_KERN, KERN_PROC, KERN_PROC_ALL, KERN_PROC_ARGS,
|
||||
TDF_IDLETD,
|
||||
CTL_HW, CTL_KERN, KERN_PROC, KERN_PROC_ALL, KERN_PROC_ARGS, TDF_IDLETD, c_char, kinfo_proc,
|
||||
sysctl,
|
||||
};
|
||||
use std::{
|
||||
ffi::CStr,
|
||||
|
@ -97,7 +97,9 @@ pub fn collect_proc(interval: Duration, _with_thread: bool) -> Vec<ProcessInfo>
|
||||
let curr_proc = if let Ok(p) = Process::new(curr_proc_pid) {
|
||||
p
|
||||
} else {
|
||||
info!("failed to retrieve info for pid={curr_proc_pid}, process probably died between snapshots");
|
||||
info!(
|
||||
"failed to retrieve info for pid={curr_proc_pid}, process probably died between snapshots"
|
||||
);
|
||||
continue;
|
||||
};
|
||||
let cwd = curr_proc.cwd().unwrap_or_default();
|
||||
|
@ -1,12 +1,12 @@
|
||||
use libc::{c_int, c_void, size_t};
|
||||
use libproc::libproc::bsd_info::BSDInfo;
|
||||
use libproc::libproc::file_info::{pidfdinfo, ListFDs, ProcFDType};
|
||||
use libproc::libproc::file_info::{ListFDs, ProcFDType, pidfdinfo};
|
||||
use libproc::libproc::net_info::{InSockInfo, SocketFDInfo, SocketInfoKind, TcpSockInfo};
|
||||
use libproc::libproc::pid_rusage::{pidrusage, RUsageInfoV2};
|
||||
use libproc::libproc::proc_pid::{listpidinfo, pidinfo, ListThreads};
|
||||
use libproc::libproc::pid_rusage::{RUsageInfoV2, pidrusage};
|
||||
use libproc::libproc::proc_pid::{ListThreads, listpidinfo, pidinfo};
|
||||
use libproc::libproc::task_info::{TaskAllInfo, TaskInfo};
|
||||
use libproc::libproc::thread_info::ThreadInfo;
|
||||
use libproc::processes::{pids_by_type, ProcFilter};
|
||||
use libproc::processes::{ProcFilter, pids_by_type};
|
||||
use mach2::mach_time;
|
||||
use std::cmp;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -155,9 +155,11 @@ pub struct PathInfo {
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked_str(cp: *mut u8, start: *mut u8) -> String {
|
||||
let len = (cp as usize).saturating_sub(start as usize);
|
||||
let part = std::slice::from_raw_parts(start, len);
|
||||
String::from_utf8_unchecked(part.to_vec())
|
||||
unsafe {
|
||||
let len = (cp as usize).saturating_sub(start as usize);
|
||||
let part = std::slice::from_raw_parts(start, len);
|
||||
String::from_utf8_unchecked(part.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_path_info(pid: i32, mut size: size_t) -> Option<PathInfo> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! This is used for both NetBSD and OpenBSD, because they are fairly similar.
|
||||
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use libc::{sysctl, CTL_HW, CTL_KERN, KERN_PROC_ALL, KERN_PROC_ARGS, KERN_PROC_ARGV};
|
||||
use libc::{CTL_HW, CTL_KERN, KERN_PROC_ALL, KERN_PROC_ARGS, KERN_PROC_ARGV, sysctl};
|
||||
use std::{
|
||||
io,
|
||||
mem::{self, MaybeUninit},
|
||||
|
@ -11,7 +11,7 @@ use ntapi::ntwow64::{PEB32, RTL_USER_PROCESS_PARAMETERS32};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::mem::{size_of, zeroed, MaybeUninit};
|
||||
use std::mem::{MaybeUninit, size_of, zeroed};
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::path::PathBuf;
|
||||
use std::ptr;
|
||||
@ -25,27 +25,27 @@ use windows::core::{PCWSTR, PWSTR};
|
||||
|
||||
use windows::Wdk::System::SystemServices::RtlGetVersion;
|
||||
use windows::Wdk::System::Threading::{
|
||||
NtQueryInformationProcess, ProcessBasicInformation, ProcessCommandLineInformation,
|
||||
ProcessWow64Information, PROCESSINFOCLASS,
|
||||
NtQueryInformationProcess, PROCESSINFOCLASS, ProcessBasicInformation,
|
||||
ProcessCommandLineInformation, ProcessWow64Information,
|
||||
};
|
||||
|
||||
use windows::Win32::Foundation::{
|
||||
CloseHandle, LocalFree, FALSE, FILETIME, HANDLE, HLOCAL, HMODULE, MAX_PATH, PSID,
|
||||
CloseHandle, FALSE, FILETIME, HANDLE, HLOCAL, HMODULE, LocalFree, MAX_PATH, PSID,
|
||||
STATUS_BUFFER_OVERFLOW, STATUS_BUFFER_TOO_SMALL, STATUS_INFO_LENGTH_MISMATCH, UNICODE_STRING,
|
||||
};
|
||||
|
||||
use windows::Win32::Security::{
|
||||
AdjustTokenPrivileges, GetTokenInformation, LookupAccountSidW, LookupPrivilegeValueW,
|
||||
TokenGroups, TokenUser, SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, SID, SID_NAME_USE,
|
||||
TOKEN_ADJUST_PRIVILEGES, TOKEN_GROUPS, TOKEN_PRIVILEGES, TOKEN_QUERY, TOKEN_USER,
|
||||
SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, SID, SID_NAME_USE, TOKEN_ADJUST_PRIVILEGES, TOKEN_GROUPS,
|
||||
TOKEN_PRIVILEGES, TOKEN_QUERY, TOKEN_USER, TokenGroups, TokenUser,
|
||||
};
|
||||
|
||||
use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory;
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::{
|
||||
CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS,
|
||||
CreateToolhelp32Snapshot, PROCESSENTRY32, Process32First, Process32Next, TH32CS_SNAPPROCESS,
|
||||
};
|
||||
|
||||
use windows::Win32::System::Memory::{VirtualQueryEx, MEMORY_BASIC_INFORMATION};
|
||||
use windows::Win32::System::Memory::{MEMORY_BASIC_INFORMATION, VirtualQueryEx};
|
||||
|
||||
use windows::Win32::System::ProcessStatus::{
|
||||
GetModuleBaseNameW, GetProcessMemoryInfo, K32EnumProcesses, PROCESS_MEMORY_COUNTERS,
|
||||
@ -55,8 +55,8 @@ use windows::Win32::System::ProcessStatus::{
|
||||
use windows::Win32::System::SystemInformation::OSVERSIONINFOEXW;
|
||||
|
||||
use windows::Win32::System::Threading::{
|
||||
GetCurrentProcess, GetPriorityClass, GetProcessIoCounters, GetProcessTimes, OpenProcess,
|
||||
OpenProcessToken, IO_COUNTERS, PEB, PROCESS_BASIC_INFORMATION, PROCESS_QUERY_INFORMATION,
|
||||
GetCurrentProcess, GetPriorityClass, GetProcessIoCounters, GetProcessTimes, IO_COUNTERS,
|
||||
OpenProcess, OpenProcessToken, PEB, PROCESS_BASIC_INFORMATION, PROCESS_QUERY_INFORMATION,
|
||||
PROCESS_VM_READ,
|
||||
};
|
||||
|
||||
@ -364,10 +364,10 @@ fn get_times(handle: HANDLE) -> Option<(u64, u64, u64, u64)> {
|
||||
&mut user as *mut FILETIME,
|
||||
);
|
||||
|
||||
let start = u64::from(start.dwHighDateTime) << 32 | u64::from(start.dwLowDateTime);
|
||||
let exit = u64::from(exit.dwHighDateTime) << 32 | u64::from(exit.dwLowDateTime);
|
||||
let sys = u64::from(sys.dwHighDateTime) << 32 | u64::from(sys.dwLowDateTime);
|
||||
let user = u64::from(user.dwHighDateTime) << 32 | u64::from(user.dwLowDateTime);
|
||||
let start = (u64::from(start.dwHighDateTime) << 32) | u64::from(start.dwLowDateTime);
|
||||
let exit = (u64::from(exit.dwHighDateTime) << 32) | u64::from(exit.dwLowDateTime);
|
||||
let sys = (u64::from(sys.dwHighDateTime) << 32) | u64::from(sys.dwLowDateTime);
|
||||
let user = (u64::from(user.dwHighDateTime) << 32) | u64::from(user.dwLowDateTime);
|
||||
|
||||
if ret.is_ok() {
|
||||
Some((start, exit, sys, user))
|
||||
@ -480,217 +480,227 @@ unsafe fn get_process_data(
|
||||
let mut buffer: Vec<u16> = Vec::with_capacity(size / 2 + 1);
|
||||
let mut bytes_read = 0;
|
||||
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
ptr,
|
||||
buffer.as_mut_ptr().cast(),
|
||||
size,
|
||||
Some(&mut bytes_read),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process data");
|
||||
}
|
||||
unsafe {
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
ptr,
|
||||
buffer.as_mut_ptr().cast(),
|
||||
size,
|
||||
Some(&mut bytes_read),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process data");
|
||||
}
|
||||
|
||||
// Documentation states that the function fails if not all data is accessible.
|
||||
if bytes_read != size {
|
||||
return Err("ReadProcessMemory returned unexpected number of bytes read");
|
||||
}
|
||||
// Documentation states that the function fails if not all data is accessible.
|
||||
if bytes_read != size {
|
||||
return Err("ReadProcessMemory returned unexpected number of bytes read");
|
||||
}
|
||||
|
||||
buffer.set_len(size / 2);
|
||||
buffer.push(0);
|
||||
buffer.set_len(size / 2);
|
||||
buffer.push(0);
|
||||
}
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
unsafe fn get_region_size(handle: HANDLE, ptr: *const c_void) -> Result<usize, &'static str> {
|
||||
let mut meminfo = MaybeUninit::<MEMORY_BASIC_INFORMATION>::uninit();
|
||||
if VirtualQueryEx(
|
||||
handle,
|
||||
Some(ptr),
|
||||
meminfo.as_mut_ptr().cast(),
|
||||
size_of::<MEMORY_BASIC_INFORMATION>(),
|
||||
) == 0
|
||||
{
|
||||
return Err("Unable to read process memory information");
|
||||
unsafe {
|
||||
let mut meminfo = MaybeUninit::<MEMORY_BASIC_INFORMATION>::uninit();
|
||||
if VirtualQueryEx(
|
||||
handle,
|
||||
Some(ptr),
|
||||
meminfo.as_mut_ptr().cast(),
|
||||
size_of::<MEMORY_BASIC_INFORMATION>(),
|
||||
) == 0
|
||||
{
|
||||
return Err("Unable to read process memory information");
|
||||
}
|
||||
let meminfo = meminfo.assume_init();
|
||||
Ok((meminfo.RegionSize as isize - ptr.offset_from(meminfo.BaseAddress)) as usize)
|
||||
}
|
||||
let meminfo = meminfo.assume_init();
|
||||
Ok((meminfo.RegionSize as isize - ptr.offset_from(meminfo.BaseAddress)) as usize)
|
||||
}
|
||||
|
||||
unsafe fn ph_query_process_variable_size(
|
||||
process_handle: HANDLE,
|
||||
process_information_class: PROCESSINFOCLASS,
|
||||
) -> Option<Vec<u16>> {
|
||||
let mut return_length = MaybeUninit::<u32>::uninit();
|
||||
unsafe {
|
||||
let mut return_length = MaybeUninit::<u32>::uninit();
|
||||
|
||||
if let Err(err) = NtQueryInformationProcess(
|
||||
process_handle,
|
||||
process_information_class,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
return_length.as_mut_ptr() as *mut _,
|
||||
)
|
||||
.ok()
|
||||
{
|
||||
if ![
|
||||
STATUS_BUFFER_OVERFLOW.into(),
|
||||
STATUS_BUFFER_TOO_SMALL.into(),
|
||||
STATUS_INFO_LENGTH_MISMATCH.into(),
|
||||
]
|
||||
.contains(&err.code())
|
||||
if let Err(err) = NtQueryInformationProcess(
|
||||
process_handle,
|
||||
process_information_class,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
return_length.as_mut_ptr() as *mut _,
|
||||
)
|
||||
.ok()
|
||||
{
|
||||
if ![
|
||||
STATUS_BUFFER_OVERFLOW.into(),
|
||||
STATUS_BUFFER_TOO_SMALL.into(),
|
||||
STATUS_INFO_LENGTH_MISMATCH.into(),
|
||||
]
|
||||
.contains(&err.code())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let mut return_length = return_length.assume_init();
|
||||
let buf_len = (return_length as usize) / 2;
|
||||
let mut buffer: Vec<u16> = Vec::with_capacity(buf_len + 1);
|
||||
if NtQueryInformationProcess(
|
||||
process_handle,
|
||||
process_information_class,
|
||||
buffer.as_mut_ptr() as *mut _,
|
||||
return_length,
|
||||
&mut return_length as *mut _,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
buffer.set_len(buf_len);
|
||||
buffer.push(0);
|
||||
Some(buffer)
|
||||
}
|
||||
|
||||
let mut return_length = return_length.assume_init();
|
||||
let buf_len = (return_length as usize) / 2;
|
||||
let mut buffer: Vec<u16> = Vec::with_capacity(buf_len + 1);
|
||||
if NtQueryInformationProcess(
|
||||
process_handle,
|
||||
process_information_class,
|
||||
buffer.as_mut_ptr() as *mut _,
|
||||
return_length,
|
||||
&mut return_length as *mut _,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
buffer.set_len(buf_len);
|
||||
buffer.push(0);
|
||||
Some(buffer)
|
||||
}
|
||||
|
||||
unsafe fn get_cmdline_from_buffer(buffer: PCWSTR) -> Vec<String> {
|
||||
// Get argc and argv from the command line
|
||||
let mut argc = MaybeUninit::<i32>::uninit();
|
||||
let argv_p = CommandLineToArgvW(buffer, argc.as_mut_ptr());
|
||||
if argv_p.is_null() {
|
||||
return Vec::new();
|
||||
unsafe {
|
||||
// Get argc and argv from the command line
|
||||
let mut argc = MaybeUninit::<i32>::uninit();
|
||||
let argv_p = CommandLineToArgvW(buffer, argc.as_mut_ptr());
|
||||
if argv_p.is_null() {
|
||||
return Vec::new();
|
||||
}
|
||||
let argc = argc.assume_init();
|
||||
let argv = std::slice::from_raw_parts(argv_p, argc as usize);
|
||||
|
||||
let mut res = Vec::new();
|
||||
for arg in argv {
|
||||
res.push(String::from_utf16_lossy(arg.as_wide()));
|
||||
}
|
||||
|
||||
let _err = LocalFree(HLOCAL(argv_p as _));
|
||||
|
||||
res
|
||||
}
|
||||
let argc = argc.assume_init();
|
||||
let argv = std::slice::from_raw_parts(argv_p, argc as usize);
|
||||
|
||||
let mut res = Vec::new();
|
||||
for arg in argv {
|
||||
res.push(String::from_utf16_lossy(arg.as_wide()));
|
||||
}
|
||||
|
||||
let _err = LocalFree(HLOCAL(argv_p as _));
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
unsafe fn get_process_params(
|
||||
handle: HANDLE,
|
||||
) -> Result<(Vec<String>, Vec<String>, PathBuf), &'static str> {
|
||||
if !cfg!(target_pointer_width = "64") {
|
||||
return Err("Non 64 bit targets are not supported");
|
||||
}
|
||||
unsafe {
|
||||
if !cfg!(target_pointer_width = "64") {
|
||||
return Err("Non 64 bit targets are not supported");
|
||||
}
|
||||
|
||||
// First check if target process is running in wow64 compatibility emulator
|
||||
let mut pwow32info = MaybeUninit::<*const c_void>::uninit();
|
||||
if NtQueryInformationProcess(
|
||||
handle,
|
||||
ProcessWow64Information,
|
||||
pwow32info.as_mut_ptr().cast(),
|
||||
size_of::<*const c_void>() as u32,
|
||||
null_mut(),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to check WOW64 information about the process");
|
||||
}
|
||||
let pwow32info = pwow32info.assume_init();
|
||||
|
||||
if pwow32info.is_null() {
|
||||
// target is a 64 bit process
|
||||
|
||||
let mut pbasicinfo = MaybeUninit::<PROCESS_BASIC_INFORMATION>::uninit();
|
||||
// First check if target process is running in wow64 compatibility emulator
|
||||
let mut pwow32info = MaybeUninit::<*const c_void>::uninit();
|
||||
if NtQueryInformationProcess(
|
||||
handle,
|
||||
ProcessBasicInformation,
|
||||
pbasicinfo.as_mut_ptr().cast(),
|
||||
size_of::<PROCESS_BASIC_INFORMATION>() as u32,
|
||||
ProcessWow64Information,
|
||||
pwow32info.as_mut_ptr().cast(),
|
||||
size_of::<*const c_void>() as u32,
|
||||
null_mut(),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to get basic process information");
|
||||
return Err("Unable to check WOW64 information about the process");
|
||||
}
|
||||
let pinfo = pbasicinfo.assume_init();
|
||||
let pwow32info = pwow32info.assume_init();
|
||||
|
||||
let mut peb = MaybeUninit::<PEB>::uninit();
|
||||
if pwow32info.is_null() {
|
||||
// target is a 64 bit process
|
||||
|
||||
let mut pbasicinfo = MaybeUninit::<PROCESS_BASIC_INFORMATION>::uninit();
|
||||
if NtQueryInformationProcess(
|
||||
handle,
|
||||
ProcessBasicInformation,
|
||||
pbasicinfo.as_mut_ptr().cast(),
|
||||
size_of::<PROCESS_BASIC_INFORMATION>() as u32,
|
||||
null_mut(),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to get basic process information");
|
||||
}
|
||||
let pinfo = pbasicinfo.assume_init();
|
||||
|
||||
let mut peb = MaybeUninit::<PEB>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
pinfo.PebBaseAddress.cast(),
|
||||
peb.as_mut_ptr().cast(),
|
||||
size_of::<PEB>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process PEB");
|
||||
}
|
||||
|
||||
let peb = peb.assume_init();
|
||||
|
||||
let mut proc_params = MaybeUninit::<RTL_USER_PROCESS_PARAMETERS>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
peb.ProcessParameters.cast(),
|
||||
proc_params.as_mut_ptr().cast(),
|
||||
size_of::<RTL_USER_PROCESS_PARAMETERS>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process parameters");
|
||||
}
|
||||
|
||||
let proc_params = proc_params.assume_init();
|
||||
return Ok((
|
||||
get_cmd_line(&proc_params, handle),
|
||||
get_proc_env(&proc_params, handle),
|
||||
get_cwd(&proc_params, handle),
|
||||
));
|
||||
}
|
||||
// target is a 32 bit process in wow64 mode
|
||||
|
||||
let mut peb32 = MaybeUninit::<PEB32>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
pinfo.PebBaseAddress.cast(),
|
||||
peb.as_mut_ptr().cast(),
|
||||
size_of::<PEB>(),
|
||||
pwow32info,
|
||||
peb32.as_mut_ptr().cast(),
|
||||
size_of::<PEB32>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process PEB");
|
||||
return Err("Unable to read PEB32");
|
||||
}
|
||||
let peb32 = peb32.assume_init();
|
||||
|
||||
let peb = peb.assume_init();
|
||||
|
||||
let mut proc_params = MaybeUninit::<RTL_USER_PROCESS_PARAMETERS>::uninit();
|
||||
let mut proc_params = MaybeUninit::<RTL_USER_PROCESS_PARAMETERS32>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
peb.ProcessParameters.cast(),
|
||||
peb32.ProcessParameters as *mut _,
|
||||
proc_params.as_mut_ptr().cast(),
|
||||
size_of::<RTL_USER_PROCESS_PARAMETERS>(),
|
||||
size_of::<RTL_USER_PROCESS_PARAMETERS32>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read process parameters");
|
||||
return Err("Unable to read 32 bit process parameters");
|
||||
}
|
||||
|
||||
let proc_params = proc_params.assume_init();
|
||||
return Ok((
|
||||
Ok((
|
||||
get_cmd_line(&proc_params, handle),
|
||||
get_proc_env(&proc_params, handle),
|
||||
get_cwd(&proc_params, handle),
|
||||
));
|
||||
))
|
||||
}
|
||||
// target is a 32 bit process in wow64 mode
|
||||
|
||||
let mut peb32 = MaybeUninit::<PEB32>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
pwow32info,
|
||||
peb32.as_mut_ptr().cast(),
|
||||
size_of::<PEB32>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read PEB32");
|
||||
}
|
||||
let peb32 = peb32.assume_init();
|
||||
|
||||
let mut proc_params = MaybeUninit::<RTL_USER_PROCESS_PARAMETERS32>::uninit();
|
||||
if ReadProcessMemory(
|
||||
handle,
|
||||
peb32.ProcessParameters as *mut _,
|
||||
proc_params.as_mut_ptr().cast(),
|
||||
size_of::<RTL_USER_PROCESS_PARAMETERS32>(),
|
||||
None,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Err("Unable to read 32 bit process parameters");
|
||||
}
|
||||
let proc_params = proc_params.assume_init();
|
||||
Ok((
|
||||
get_cmd_line(&proc_params, handle),
|
||||
get_proc_env(&proc_params, handle),
|
||||
get_cwd(&proc_params, handle),
|
||||
))
|
||||
}
|
||||
|
||||
static WINDOWS_8_1_OR_NEWER: LazyLock<bool> = LazyLock::new(|| unsafe {
|
||||
|
Reference in New Issue
Block a user