Skip to content

Commit 1ca54e4

Browse files
committed
Procces api fallbacks for 9x/ME/NT
9x/ME: - Don't use `CREATE_UNICODE_ENVIRONMENT` - Use `command.com` instead of `cmd.exe` - Use `NUL` instead of `\\.\NUL` NT: - Use /X instead of /e:ON for support for ancient cmd.exe versions
1 parent f86cf22 commit 1ca54e4

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

library/std/src/sys/pal/windows/args.rs

+10
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,17 @@ pub(crate) fn make_bat_command_line(
333333
// hence the trailing quote here. It will be closed after all arguments
334334
// have been added.
335335
// Using /e:ON enables "command extensions" which is essential for the `%` hack to work.
336+
#[cfg(not(target_vendor = "rust9x"))]
336337
let mut cmd: Vec<u16> = "cmd.exe /e:ON /v:OFF /d /c \"".encode_utf16().collect();
338+
#[cfg(target_vendor = "rust9x")]
339+
let mut cmd: Vec<u16> = if crate::sys::compat::checks::is_windows_nt() {
340+
// Using /X instead of /e:ON for old NT versions.
341+
"cmd.exe /X /v:OFF /d /c \""
342+
} else {
343+
"command.com /c \""
344+
}
345+
.encode_utf16()
346+
.collect();
337347

338348
// Push the script name surrounded by its quote pair.
339349
cmd.push(b'"' as u16);

library/std/src/sys/pal/windows/process.rs

+63-6
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,28 @@ impl Command {
288288
None
289289
};
290290
let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?;
291+
#[cfg(not(target_vendor = "rust9x"))]
291292
let has_bat_extension = |program: &[u16]| {
292293
matches!(
293294
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
294295
program.len().checked_sub(4).and_then(|i| program.get(i..)),
295296
Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68])
296297
)
297298
};
299+
#[cfg(target_vendor = "rust9x")]
300+
let has_bat_extension = |program: &[u16]| {
301+
let ext = program.len().checked_sub(4).and_then(|i| program.get(i..));
302+
if crate::sys::compat::checks::is_windows_nt() {
303+
matches!(
304+
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
305+
ext,
306+
Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68])
307+
)
308+
} else {
309+
// Case insensitive "ends_with" of UTF-16 encoded ".bat"
310+
matches!(ext, Some([46, 98 | 66, 97 | 65, 116 | 84, 0]))
311+
}
312+
};
298313
let is_batch_file = if path::is_verbatim(&program) {
299314
has_bat_extension(&program[..program.len() - 1])
300315
} else {
@@ -318,7 +333,16 @@ impl Command {
318333
cmd_str.push(0); // add null terminator
319334

320335
// stolen from the libuv code.
336+
#[cfg(not(target_vendor = "rust9x"))]
321337
let mut flags = self.flags | c::CREATE_UNICODE_ENVIRONMENT;
338+
#[cfg(target_vendor = "rust9x")]
339+
let mut flags = {
340+
let mut flags = self.flags;
341+
if crate::sys::compat::checks::is_windows_nt() {
342+
flags |= c::CREATE_UNICODE_ENVIRONMENT;
343+
}
344+
flags
345+
};
322346
if self.detach {
323347
flags |= c::DETACHED_PROCESS | c::CREATE_NEW_PROCESS_GROUP;
324348
}
@@ -640,6 +664,17 @@ impl Stdio {
640664
opts.read(stdio_id == c::STD_INPUT_HANDLE);
641665
opts.write(stdio_id != c::STD_INPUT_HANDLE);
642666
opts.security_attributes(&mut sa);
667+
668+
#[cfg(target_vendor = "rust9x")]
669+
{
670+
let p = if crate::sys::compat::checks::is_windows_nt() {
671+
r"\\.\NUL"
672+
} else {
673+
r"NUL"
674+
};
675+
File::open(Path::new(p), &opts).map(|file| file.into_inner())
676+
}
677+
#[cfg(not(target_vendor = "rust9x"))]
643678
File::open(Path::new(r"\\.\NUL"), &opts).map(|file| file.into_inner())
644679
}
645680
}
@@ -877,12 +912,34 @@ fn make_command_line(argv0: &OsStr, args: &[Arg], force_quotes: bool) -> io::Res
877912

878913
// Get `cmd.exe` for use with bat scripts, encoded as a UTF-16 string.
879914
fn command_prompt() -> io::Result<Vec<u16>> {
880-
let mut system: Vec<u16> = super::fill_utf16_buf(
881-
|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) },
882-
|buf| buf.into(),
883-
)?;
884-
system.extend("\\cmd.exe".encode_utf16().chain([0]));
885-
Ok(system)
915+
#[cfg(target_vendor = "rust9x")]
916+
{
917+
if crate::sys::compat::checks::is_windows_nt() {
918+
let mut system: Vec<u16> = super::fill_utf16_buf(
919+
|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) },
920+
|buf| buf.into(),
921+
)?;
922+
system.extend("\\cmd.exe".encode_utf16().chain([0]));
923+
Ok(system)
924+
} else {
925+
let mut system: Vec<u16> = super::fill_utf16_buf(
926+
|buf, size| unsafe { c::GetWindowsDirectoryW(buf, size) },
927+
|buf| buf.into(),
928+
)?;
929+
system.extend("\\command.com".encode_utf16().chain([0]));
930+
Ok(system)
931+
}
932+
}
933+
934+
#[cfg(not(target_vendor = "rust9x"))]
935+
{
936+
let mut system: Vec<u16> = super::fill_utf16_buf(
937+
|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) },
938+
|buf| buf.into(),
939+
)?;
940+
system.extend("\\cmd.exe".encode_utf16().chain([0]));
941+
Ok(system)
942+
}
886943
}
887944

888945
fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>) -> io::Result<(*mut c_void, Vec<u16>)> {

0 commit comments

Comments
 (0)