How to create a fifo in windows?

I want to convert this linux code to windows code:

use nix::{sys::stat, unistd};
// fifo_path: &PathBuf
unistd::mkfifo(fifo_path, stat::Mode::from_bits(0o600).unwrap()).context("Error creating FIFO pipe")?;

error[E0432]: unresolved imports `nix::sys` , `nix::unistd`
--> src\cwe_checker_lib\src\utils\ghidra.rs:13:11
|
13 | use nix::{sys::stat, unistd};
| ^^^ ^^^^^^ no `unistd` in the root
| |
| could not find `sys` in `nix`

I try this way but fail:

// The first way:

// use std::ptr;
// use winapi::um::namedpipeapi::{CreateNamedPipeW, PIPE_ACCESS_DUPLEX};
// use winapi::um::winbase::{PIPE_READMODE_BYTE, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES};
// use winapi::um::winnt::FILE_FLAG_OVERLAPPED;
// unsafe {
    //     let handle = CreateNamedPipeW(
    //         fifo_path,
    //         PIPE_ACCESS_DUPLEX,
    //         PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    //         PIPE_UNLIMITED_INSTANCES,
    //         0,
    //         0,
    //         0,
    //         ptr::null_mut(),
    //     );
    //     if handle == ptr::null_mut() {
    //         return Err(std::io::Error::last_os_error());
    //     }
    // }
    
// The second way:

// use windows::{
//     core::*,
//     Win32::{FileManagement::*, Foundation::*, System::Threading::*},
// };
// let pipe_name: HSTRING = HSTRING::from(fifo_path);
    // // 设置管道的各种属性,这里示例设置了一些基本属性,可根据需求调整
    // let pipe_attributes = CreatePipeAttributes {
    //     dwFlags: PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPING,
    //     dwMaxInstances: 1,
    //     nOutBufferSize: 0,
    //     nInBufferSize: 0,
    //     nDefaultTimeOut: 0,
    // };
    // let security_attributes = SECURITY_ATTRIBUTES {
    //     nLength: std::mem::size_of::<SECURITY_ATTRIBUTES>() as u32,
    //     lpSecurityDescriptor: None,
    //     bInheritHandle: false,
    // };
    // // 创建命名管道
    // let pipe_handle = unsafe {
    //     CreateNamedPipeW(
    //         pipe_name,
    //         pipe_attributes.dwFlags,
    //         PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
    //         pipe_attributes.dwMaxInstances,
    //         pipe_attributes.nOutBufferSize,
    //         pipe_attributes.nInBufferSize,
    //         pipe_attributes.nDefaultTimeOut,
    //         Some(&security_attributes),
    //     )
    // };
    // if pipe_handle.is_invalid() {
    //     return Err(Box::new(std::io::Error::last_error()));
    // }


// The third way:

extern crate libc;
use libc::mkfifo;
use libc::mode_t;
use std::ffi::CString;
    //let filename = CString::new(fifo_path.display()).unwrap();
    unsafe {
        libc::mkfifo(fifo_path, 0o644);
    }

can't find the winapi、Win32

error[E0432]: unresolved import `libc::mkfifo`
  --> src\cwe_checker_lib\src\utils\ghidra.rs:27:5

nix = "0.29.0"
windows = "0.58.0"
libc = "0.2"

Not a rust question per se. And I'm not a Windows expert. Checking the Wikipedia article on the topic it appears named pipes on Windows have very different semantics: they live in a separate namespace from the normal file system, and are removed once the last user closed the pipe.

It does not appear that the nix crate support them on Windows, so you would likely need to use a windows API crate directly.

Windows also doesn't use modes, but ACLs, so that bit also won't work the same.

Porting this software might be non-trivial.

Remove these two lines of codes, then I compiled sucessfully and got the executable file, but can't run because next logic is to open the fifo file.

thread 'main' panicked at src\cwe_checker_lib\src\utils\ghidra.rs:240:63:
Could not open FIFO.: Os { code: 2, kind: NotFound, message: "系统找不到指定的文件。" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Then I used CreateNamedPipeW api and compiled successfully :

let wide: Vec<u16> = OsString::from(fifo_path.clone().into_os_string().into_string().unwrap())
        .encode_wide()
        .collect();
    let wide_null_terminated: Vec<u16> = wide.into_iter().chain(std::iter::once(0)).collect(); // 添加null终止符
unsafe {
        let handle = CreateNamedPipeW(
            // os_str.unwrap(),
            wide_null_terminated.as_ptr(),
            // pathbuf_to_lpcwstr(fifo_path),
            PIPE_ACCESS_DUPLEX,
            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
            PIPE_UNLIMITED_INSTANCES,
            0,
            0,
            0,
            ptr::null_mut(),
        );
        if handle == ptr::null_mut() {
            println!(
                "execute_ghidra, handle == ptr::null_mut() {}",
                fifo_path.display()
            );
            // context("Error execute_ghidra, handle == ptr::null_mut()");
            // return Err(std::io::Error::last_os_error());
        } else {
            match String::from_utf16(wide_null_terminated.as_slice()) {
                Ok(s) => println!("execute_ghidra, handle != ptr::null_mut() {}", s),
                Err(e) => println!("Invalid UTF-16 sequence: {:?}", e),
            }
        }
}

But when I run, still not found the created file and got an error.

On windows pipes can only be created with very specific names

I create a FIFO use this code:

let _ = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(fifo_path.clone())
            .map(|_| ());

It seems to have no asynchronous functionality.

So I exchange the order: firstly call the command and then read the result file:

ghidra_subprocess
            .join()
            .expect("The Ghidra thread to be joined has panicked!");

// Open the FIFO
let mut file = std::fs::File::open(fifo_path.clone()).expect("Could not open FIFO.");
let mut buf = String::new();
file.read_to_string(&mut buf)
    .expect("Error while reading from FIFO.");
debug_settings.print(&buf, debug::Stage::Pcode(debug::PcodeForm::Raw));
let pcode_parsing_result = serde_json::from_str(&buf);