@@ -1645,28 +1645,24 @@ impl AsRawHandle for NamedPipeClient {
16451645 }
16461646}
16471647
1648- // Helper to set a boolean flag as a bitfield.
1649- macro_rules! bool_flag {
1650- ( $f: expr, $t: expr, $flag: expr) => { {
1651- let current = $f;
1652-
1653- if $t {
1654- $f = current | $flag;
1655- } else {
1656- $f = current & !$flag;
1657- } ;
1658- } } ;
1659- }
1660-
16611648/// A builder structure for construct a named pipe with named pipe-specific
16621649/// options. This is required to use for named pipe servers who wants to modify
16631650/// pipe-related options.
16641651///
16651652/// See [`ServerOptions::create`].
16661653#[ derive( Debug , Clone ) ]
16671654pub struct ServerOptions {
1668- open_mode : u32 ,
1669- pipe_mode : u32 ,
1655+ // dwOpenMode
1656+ access_inbound : bool ,
1657+ access_outbound : bool ,
1658+ first_pipe_instance : bool ,
1659+ write_dac : bool ,
1660+ write_owner : bool ,
1661+ access_system_security : bool ,
1662+ // dwPipeMode
1663+ pipe_mode : PipeMode ,
1664+ reject_remote_clients : bool ,
1665+ // other options
16701666 max_instances : u32 ,
16711667 out_buffer_size : u32 ,
16721668 in_buffer_size : u32 ,
@@ -1687,8 +1683,14 @@ impl ServerOptions {
16871683 /// ```
16881684 pub fn new ( ) -> ServerOptions {
16891685 ServerOptions {
1690- open_mode : windows_sys:: PIPE_ACCESS_DUPLEX | windows_sys:: FILE_FLAG_OVERLAPPED ,
1691- pipe_mode : windows_sys:: PIPE_TYPE_BYTE | windows_sys:: PIPE_REJECT_REMOTE_CLIENTS ,
1686+ access_inbound : true ,
1687+ access_outbound : true ,
1688+ first_pipe_instance : false ,
1689+ write_dac : false ,
1690+ write_owner : false ,
1691+ access_system_security : false ,
1692+ pipe_mode : PipeMode :: Byte ,
1693+ reject_remote_clients : true ,
16921694 max_instances : windows_sys:: PIPE_UNLIMITED_INSTANCES ,
16931695 out_buffer_size : 65536 ,
16941696 in_buffer_size : 65536 ,
@@ -1705,14 +1707,7 @@ impl ServerOptions {
17051707 ///
17061708 /// [`dwPipeMode`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
17071709 pub fn pipe_mode ( & mut self , pipe_mode : PipeMode ) -> & mut Self {
1708- let is_msg = matches ! ( pipe_mode, PipeMode :: Message ) ;
1709- // Pipe mode is implemented as a bit flag 0x4. Set is message and unset
1710- // is byte.
1711- bool_flag ! (
1712- self . pipe_mode,
1713- is_msg,
1714- windows_sys:: PIPE_TYPE_MESSAGE | windows_sys:: PIPE_READMODE_MESSAGE
1715- ) ;
1710+ self . pipe_mode = pipe_mode;
17161711 self
17171712 }
17181713
@@ -1808,7 +1803,7 @@ impl ServerOptions {
18081803 /// # Ok(()) }
18091804 /// ```
18101805 pub fn access_inbound ( & mut self , allowed : bool ) -> & mut Self {
1811- bool_flag ! ( self . open_mode , allowed , windows_sys :: PIPE_ACCESS_INBOUND ) ;
1806+ self . access_inbound = allowed ;
18121807 self
18131808 }
18141809
@@ -1906,7 +1901,7 @@ impl ServerOptions {
19061901 /// # Ok(()) }
19071902 /// ```
19081903 pub fn access_outbound ( & mut self , allowed : bool ) -> & mut Self {
1909- bool_flag ! ( self . open_mode , allowed , windows_sys :: PIPE_ACCESS_OUTBOUND ) ;
1904+ self . access_outbound = allowed ;
19101905 self
19111906 }
19121907
@@ -1974,11 +1969,7 @@ impl ServerOptions {
19741969 /// [`create`]: ServerOptions::create
19751970 /// [`FILE_FLAG_FIRST_PIPE_INSTANCE`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#pipe_first_pipe_instance
19761971 pub fn first_pipe_instance ( & mut self , first : bool ) -> & mut Self {
1977- bool_flag ! (
1978- self . open_mode,
1979- first,
1980- windows_sys:: FILE_FLAG_FIRST_PIPE_INSTANCE
1981- ) ;
1972+ self . first_pipe_instance = first;
19821973 self
19831974 }
19841975
@@ -2060,7 +2051,7 @@ impl ServerOptions {
20602051 ///
20612052 /// [`WRITE_DAC`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20622053 pub fn write_dac ( & mut self , requested : bool ) -> & mut Self {
2063- bool_flag ! ( self . open_mode , requested , windows_sys :: WRITE_DAC ) ;
2054+ self . write_dac = requested ;
20642055 self
20652056 }
20662057
@@ -2070,7 +2061,7 @@ impl ServerOptions {
20702061 ///
20712062 /// [`WRITE_OWNER`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20722063 pub fn write_owner ( & mut self , requested : bool ) -> & mut Self {
2073- bool_flag ! ( self . open_mode , requested , windows_sys :: WRITE_OWNER ) ;
2064+ self . write_owner = requested ;
20742065 self
20752066 }
20762067
@@ -2080,11 +2071,7 @@ impl ServerOptions {
20802071 ///
20812072 /// [`ACCESS_SYSTEM_SECURITY`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20822073 pub fn access_system_security ( & mut self , requested : bool ) -> & mut Self {
2083- bool_flag ! (
2084- self . open_mode,
2085- requested,
2086- windows_sys:: ACCESS_SYSTEM_SECURITY
2087- ) ;
2074+ self . access_system_security = requested;
20882075 self
20892076 }
20902077
@@ -2095,11 +2082,7 @@ impl ServerOptions {
20952082 ///
20962083 /// [`PIPE_REJECT_REMOTE_CLIENTS`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#pipe_reject_remote_clients
20972084 pub fn reject_remote_clients ( & mut self , reject : bool ) -> & mut Self {
2098- bool_flag ! (
2099- self . pipe_mode,
2100- reject,
2101- windows_sys:: PIPE_REJECT_REMOTE_CLIENTS
2102- ) ;
2085+ self . reject_remote_clients = reject;
21032086 self
21042087 }
21052088
@@ -2245,10 +2228,46 @@ impl ServerOptions {
22452228 ) -> io:: Result < NamedPipeServer > {
22462229 let addr = encode_addr ( addr) ;
22472230
2231+ let pipe_mode = {
2232+ let mut mode = if matches ! ( self . pipe_mode, PipeMode :: Message ) {
2233+ windows_sys:: PIPE_TYPE_MESSAGE | windows_sys:: PIPE_READMODE_MESSAGE
2234+ } else {
2235+ windows_sys:: PIPE_TYPE_BYTE | windows_sys:: PIPE_READMODE_BYTE
2236+ } ;
2237+ if self . reject_remote_clients {
2238+ mode |= windows_sys:: PIPE_REJECT_REMOTE_CLIENTS ;
2239+ } else {
2240+ mode |= windows_sys:: PIPE_ACCEPT_REMOTE_CLIENTS ;
2241+ }
2242+ mode
2243+ } ;
2244+ let open_mode = {
2245+ let mut mode = windows_sys:: FILE_FLAG_OVERLAPPED ;
2246+ if self . access_inbound {
2247+ mode |= windows_sys:: PIPE_ACCESS_INBOUND ;
2248+ }
2249+ if self . access_outbound {
2250+ mode |= windows_sys:: PIPE_ACCESS_OUTBOUND ;
2251+ }
2252+ if self . first_pipe_instance {
2253+ mode |= windows_sys:: FILE_FLAG_FIRST_PIPE_INSTANCE ;
2254+ }
2255+ if self . write_dac {
2256+ mode |= windows_sys:: WRITE_DAC ;
2257+ }
2258+ if self . write_owner {
2259+ mode |= windows_sys:: WRITE_OWNER ;
2260+ }
2261+ if self . access_system_security {
2262+ mode |= windows_sys:: ACCESS_SYSTEM_SECURITY ;
2263+ }
2264+ mode
2265+ } ;
2266+
22482267 let h = windows_sys:: CreateNamedPipeW (
22492268 addr. as_ptr ( ) ,
2250- self . open_mode ,
2251- self . pipe_mode ,
2269+ open_mode,
2270+ pipe_mode,
22522271 self . max_instances ,
22532272 self . out_buffer_size ,
22542273 self . in_buffer_size ,
@@ -2270,7 +2289,8 @@ impl ServerOptions {
22702289/// See [`ClientOptions::open`].
22712290#[ derive( Debug , Clone ) ]
22722291pub struct ClientOptions {
2273- desired_access : u32 ,
2292+ generic_read : bool ,
2293+ generic_write : bool ,
22742294 security_qos_flags : u32 ,
22752295 pipe_mode : PipeMode ,
22762296}
@@ -2291,7 +2311,8 @@ impl ClientOptions {
22912311 /// ```
22922312 pub fn new ( ) -> Self {
22932313 Self {
2294- desired_access : windows_sys:: GENERIC_READ | windows_sys:: GENERIC_WRITE ,
2314+ generic_read : true ,
2315+ generic_write : true ,
22952316 security_qos_flags : windows_sys:: SECURITY_IDENTIFICATION
22962317 | windows_sys:: SECURITY_SQOS_PRESENT ,
22972318 pipe_mode : PipeMode :: Byte ,
@@ -2305,7 +2326,7 @@ impl ClientOptions {
23052326 /// [`GENERIC_READ`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
23062327 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
23072328 pub fn read ( & mut self , allowed : bool ) -> & mut Self {
2308- bool_flag ! ( self . desired_access , allowed , windows_sys :: GENERIC_READ ) ;
2329+ self . generic_read = allowed ;
23092330 self
23102331 }
23112332
@@ -2316,7 +2337,7 @@ impl ClientOptions {
23162337 /// [`GENERIC_WRITE`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
23172338 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
23182339 pub fn write ( & mut self , allowed : bool ) -> & mut Self {
2319- bool_flag ! ( self . desired_access , allowed , windows_sys :: GENERIC_WRITE ) ;
2340+ self . generic_write = allowed ;
23202341 self
23212342 }
23222343
@@ -2434,13 +2455,24 @@ impl ClientOptions {
24342455 ) -> io:: Result < NamedPipeClient > {
24352456 let addr = encode_addr ( addr) ;
24362457
2458+ let desired_access = {
2459+ let mut access = 0 ;
2460+ if self . generic_read {
2461+ access |= windows_sys:: GENERIC_READ ;
2462+ }
2463+ if self . generic_write {
2464+ access |= windows_sys:: GENERIC_WRITE ;
2465+ }
2466+ access
2467+ } ;
2468+
24372469 // NB: We could use a platform specialized `OpenOptions` here, but since
24382470 // we have access to windows_sys it ultimately doesn't hurt to use
24392471 // `CreateFile` explicitly since it allows the use of our already
24402472 // well-structured wide `addr` to pass into CreateFileW.
24412473 let h = windows_sys:: CreateFileW (
24422474 addr. as_ptr ( ) ,
2443- self . desired_access ,
2475+ desired_access,
24442476 0 ,
24452477 attrs as * mut _ ,
24462478 windows_sys:: OPEN_EXISTING ,
@@ -2582,48 +2614,3 @@ unsafe fn named_pipe_info(handle: RawHandle) -> io::Result<PipeInfo> {
25822614 max_instances,
25832615 } )
25842616}
2585-
2586- #[ cfg( test) ]
2587- mod test {
2588- use self :: windows_sys:: { PIPE_REJECT_REMOTE_CLIENTS , PIPE_TYPE_BYTE , PIPE_TYPE_MESSAGE , PIPE_READMODE_MESSAGE } ;
2589- use super :: * ;
2590-
2591- #[ test]
2592- fn opts_default_pipe_mode ( ) {
2593- let opts = ServerOptions :: new ( ) ;
2594- assert_eq ! ( opts. pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS ) ;
2595- }
2596-
2597- #[ test]
2598- fn opts_unset_reject_remote ( ) {
2599- let mut opts = ServerOptions :: new ( ) ;
2600- opts. reject_remote_clients ( false ) ;
2601- assert_eq ! ( opts. pipe_mode & PIPE_REJECT_REMOTE_CLIENTS , 0 ) ;
2602- }
2603-
2604- #[ test]
2605- fn opts_set_pipe_mode_maintains_reject_remote_clients ( ) {
2606- let mut opts = ServerOptions :: new ( ) ;
2607- opts. pipe_mode ( PipeMode :: Byte ) ;
2608- assert_eq ! ( opts. pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS ) ;
2609-
2610- opts. reject_remote_clients ( false ) ;
2611- opts. pipe_mode ( PipeMode :: Byte ) ;
2612- assert_eq ! ( opts. pipe_mode, PIPE_TYPE_BYTE ) ;
2613-
2614- opts. reject_remote_clients ( true ) ;
2615- opts. pipe_mode ( PipeMode :: Byte ) ;
2616- assert_eq ! ( opts. pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS ) ;
2617-
2618- opts. reject_remote_clients ( false ) ;
2619- opts. pipe_mode ( PipeMode :: Message ) ;
2620- assert_eq ! ( opts. pipe_mode, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE ) ;
2621-
2622- opts. reject_remote_clients ( true ) ;
2623- opts. pipe_mode ( PipeMode :: Message ) ;
2624- assert_eq ! (
2625- opts. pipe_mode,
2626- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS
2627- ) ;
2628- }
2629- }
0 commit comments