Reading/Writing from Windows Named Pipe

Viewed 910

I have been trying to use the named pipes on Windows 10, but for some reason it doesn't seem to be either writing to it or reading from it correctly.

Running the below code will block on the spawned thread (output.read()) waiting for bytes to be written with input.write.

Let me know if I should add the imports.

fn main() {
    let pipes = create_pipe(Path::new(r#"\\.\pipe\input"#));

    let mut server: File = unsafe { File::from_raw_handle(pipes.0.as_raw_handle()) };
    let client: File = unsafe { File::from_raw_handle(pipes.1.as_raw_handle()) };

    let mut input = BufWriter::new(server);
    let mut output = BufReader::new(client);

    thread::spawn(move || {
        let mut message = vec![];
        loop {
            output.read(&mut message).unwrap();
            println!("m: {:#?}", message);
        }
    });

    loop {
        input.write("test".as_bytes()).unwrap();
        thread::sleep(Duration::from_secs(1));
    }
}

fn create_pipe(path: &Path) -> (Handle, Handle) {
    let mut os_str: OsString = path.as_os_str().into();
    os_str.push("\x00");
    let u16_slice = os_str.encode_wide().collect::<Vec<u16>>();

    let access_flags =
        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC;

    let server_handle: RawHandle = unsafe {
        namedpipeapi::CreateNamedPipeW(
            u16_slice.as_ptr(),
            access_flags,
            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
            1,
            65536,
            65536,
            0,
            ptr::null_mut(),
        )
    };

    let mut attributes = SECURITY_ATTRIBUTES {
        nLength: mem::size_of::<SECURITY_ATTRIBUTES>() as DWORD,
        lpSecurityDescriptor: ptr::null_mut(),
        bInheritHandle: true as BOOL,
    };

    let child_handle: RawHandle = unsafe {
        fileapi::CreateFileW(
            u16_slice.as_ptr(),
            GENERIC_READ | GENERIC_WRITE | FILE_READ_ATTRIBUTES,
            0,
            &mut attributes as LPSECURITY_ATTRIBUTES,
            OPEN_EXISTING,
            0,
            ptr::null_mut(),
        )
    };

    if server_handle != INVALID_HANDLE_VALUE && child_handle != INVALID_HANDLE_VALUE {
        let ret = unsafe { ConnectNamedPipe(server_handle, ptr::null_mut()) != 0 };
        if !ret {
            let err = unsafe { GetLastError() };
            if err != 535 {
                panic!("Pipe error");
            }
        }
        (Handle(server_handle), Handle(child_handle))
    } else {
        panic!(io::Error::last_os_error())
    }
}

#[derive(Debug)]
pub struct Handle(RawHandle);

unsafe impl Send for Handle {}

impl AsRawHandle for Handle {
    fn as_raw_handle(&self) -> RawHandle {
        self.0
    }
}

impl FromRawHandle for Handle {
    unsafe fn from_raw_handle(handle: RawHandle) -> Handle {
        Handle(handle)
    }
}
0 Answers
Related