Skip to content

Commit 4c7caeb

Browse files
committed
Process 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 d96c992 commit 4c7caeb

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,28 @@ impl Command {
284284
None
285285
};
286286
let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?;
287+
#[cfg(not(target_vendor = "rust9x"))]
287288
let has_bat_extension = |program: &[u16]| {
288289
matches!(
289290
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
290291
program.len().checked_sub(4).and_then(|i| program.get(i..)),
291292
Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68])
292293
)
293294
};
295+
#[cfg(target_vendor = "rust9x")]
296+
let has_bat_extension = |program: &[u16]| {
297+
let ext = program.len().checked_sub(4).and_then(|i| program.get(i..));
298+
if crate::sys::compat::checks::is_windows_nt() {
299+
matches!(
300+
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
301+
ext,
302+
Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68])
303+
)
304+
} else {
305+
// Case insensitive "ends_with" of UTF-16 encoded ".bat"
306+
matches!(ext, Some([46, 98 | 66, 97 | 65, 116 | 84, 0]))
307+
}
308+
};
294309
let is_batch_file = if path::is_verbatim(&program) {
295310
has_bat_extension(&program[..program.len() - 1])
296311
} else {
@@ -314,7 +329,16 @@ impl Command {
314329
cmd_str.push(0); // add null terminator
315330

316331
// stolen from the libuv code.
332+
#[cfg(not(target_vendor = "rust9x"))]
317333
let mut flags = self.flags | c::CREATE_UNICODE_ENVIRONMENT;
334+
#[cfg(target_vendor = "rust9x")]
335+
let mut flags = {
336+
let mut flags = self.flags;
337+
if crate::sys::compat::checks::is_windows_nt() {
338+
flags |= c::CREATE_UNICODE_ENVIRONMENT;
339+
}
340+
flags
341+
};
318342
if self.detach {
319343
flags |= c::DETACHED_PROCESS | c::CREATE_NEW_PROCESS_GROUP;
320344
}
@@ -637,6 +661,17 @@ impl Stdio {
637661
opts.read(stdio_id == c::STD_INPUT_HANDLE);
638662
opts.write(stdio_id != c::STD_INPUT_HANDLE);
639663
opts.security_attributes(&mut sa);
664+
665+
#[cfg(target_vendor = "rust9x")]
666+
{
667+
let p = if crate::sys::compat::checks::is_windows_nt() {
668+
r"\\.\NUL"
669+
} else {
670+
r"NUL"
671+
};
672+
File::open(Path::new(p), &opts).map(|file| file.into_inner())
673+
}
674+
#[cfg(not(target_vendor = "rust9x"))]
640675
File::open(Path::new(r"\\.\NUL"), &opts).map(|file| file.into_inner())
641676
}
642677
}
@@ -874,12 +909,34 @@ fn make_command_line(argv0: &OsStr, args: &[Arg], force_quotes: bool) -> io::Res
874909

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

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

0 commit comments

Comments
 (0)