Repository: denoland/deno
Pull request: fix(ext/node): stat.mode on windows

Fixes https://github.com/denoland/deno/issues/23984

Changed files:
filename: Cargo.lock
patch: @@ -1525,6 +1525,7 @@ dependencies = [
  "rayon",
  "serde",
  "winapi",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1791,7 +1792,7 @@ dependencies = [
  "tokio",
  "url",
  "winapi",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
  "x25519-dalek",
  "x509-parser",
 ]
@@ -1904,7 +1905,7 @@ dependencies = [
  "uuid",
  "which 4.4.2",
  "winapi",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]

filename: Cargo.toml
patch: @@ -211,7 +211,7 @@ nix = "=0.26.2"
 # windows deps
 junction = "=0.2.0"
 winapi = "=0.3.9"
-windows-sys = { version = "0.48.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem"] }
+windows-sys = { version = "0.52.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_WindowsProgramming", "Wdk", "Wdk_System", "Wdk_System_SystemInformation", "Win32_System_Pipes", "Wdk_Storage_FileSystem", "Win32_System_Registry"] }
 winres = "=0.1.12"
 
 # NB: the `bench` and `release` profiles must remain EXACTLY the same.

filename: ext/fs/Cargo.toml
patch: @@ -34,4 +34,5 @@ nix.workspace = true
 
 [target.'cfg(windows)'.dependencies]
 winapi = { workspace = true, features = ["winbase"] }
+windows-sys.workspace = true
 junction.workspace = true

filename: ext/fs/std_fs.rs
patch: @@ -821,6 +821,29 @@ fn stat_extra(
     Ok(info.dwVolumeSerialNumber as u64)
   }
 
+  use windows_sys::Wdk::Storage::FileSystem::FILE_ALL_INFORMATION;
+
+  unsafe fn query_file_information(
+    handle: winapi::shared::ntdef::HANDLE,
+  ) -> std::io::Result<FILE_ALL_INFORMATION> {
+    use windows_sys::Wdk::Storage::FileSystem::NtQueryInformationFile;
+
+    let mut info = std::mem::MaybeUninit::<FILE_ALL_INFORMATION>::zeroed();
+    let status = NtQueryInformationFile(
+      handle as _,
+      std::ptr::null_mut(),
+      info.as_mut_ptr() as *mut _,
+      std::mem::size_of::<FILE_ALL_INFORMATION>() as _,
+      18, /* FileAllInformation */
+    );
+
+    if status < 0 {
+      return Err(std::io::Error::last_os_error());
+    }
+
+    Ok(info.assume_init())
+  }
+
   // SAFETY: winapi calls
   unsafe {
     let mut path: Vec<_> = path.as_os_str().encode_wide().collect();
@@ -842,6 +865,39 @@ fn stat_extra(
     CloseHandle(file_handle);
     fsstat.dev = result?;
 
+    if let Ok(file_info) = query_file_information(file_handle) {
+      if file_info.BasicInformation.FileAttributes
+        & winapi::um::winnt::FILE_ATTRIBUTE_REPARSE_POINT
+        != 0
+      {
+        fsstat.is_symlink = true;
+      }
+
+      if file_info.BasicInformation.FileAttributes
+        & winapi::um::winnt::FILE_ATTRIBUTE_DIRECTORY
+        != 0
+      {
+        fsstat.mode |= libc::S_IFDIR as u32;
+        fsstat.size = 0;
+      } else {
+        fsstat.mode |= libc::S_IFREG as u32;
+        fsstat.size = file_info.StandardInformation.EndOfFile as u64;
+      }
+
+      if file_info.BasicInformation.FileAttributes
+        & winapi::um::winnt::FILE_ATTRIBUTE_READONLY
+        != 0
+      {
+        fsstat.mode |=
+          (libc::S_IREAD | (libc::S_IREAD >> 3) | (libc::S_IREAD >> 6)) as u32;
+      } else {
+        fsstat.mode |= ((libc::S_IREAD | libc::S_IWRITE)
+          | ((libc::S_IREAD | libc::S_IWRITE) >> 3)
+          | ((libc::S_IREAD | libc::S_IWRITE) >> 6))
+          as u32;
+      }
+    }
+
     Ok(())
   }
 }

filename: ext/node/ops/os/cpus.rs
patch: @@ -122,8 +122,8 @@ pub fn cpu_info() -> Option<Vec<CpuInfo>> {
 
 #[cfg(target_os = "windows")]
 pub fn cpu_info() -> Option<Vec<CpuInfo>> {
-  use windows_sys::Win32::System::WindowsProgramming::NtQuerySystemInformation;
-  use windows_sys::Win32::System::WindowsProgramming::SystemProcessorPerformanceInformation;
+  use windows_sys::Wdk::System::SystemInformation::NtQuerySystemInformation;
+  use windows_sys::Wdk::System::SystemInformation::SystemProcessorPerformanceInformation;
   use windows_sys::Win32::System::WindowsProgramming::SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
 
   use std::os::windows::ffi::OsStrExt;