@@ -74,20 +74,10 @@ impl FromRawHandle for Handle {
7474
7575impl  Handle  { 
7676    pub  fn  read ( & self ,  buf :  & mut  [ u8 ] )  -> io:: Result < usize >  { 
77-         let  mut  read = 0 ; 
78-         let  len = cmp:: min ( buf. len ( ) ,  <c:: DWORD >:: MAX  as  usize )  as  c:: DWORD ; 
79-         let  res = cvt ( unsafe  { 
80-             c:: ReadFile ( 
81-                 self . as_handle ( ) , 
82-                 buf. as_mut_ptr ( )  as  c:: LPVOID , 
83-                 len, 
84-                 & mut  read, 
85-                 ptr:: null_mut ( ) , 
86-             ) 
87-         } ) ; 
77+         let  res = unsafe  {  self . synchronous_read ( buf. as_mut_ptr ( ) . cast ( ) ,  buf. len ( ) ,  None )  } ; 
8878
8979        match  res { 
90-             Ok ( _ )  => Ok ( read as  usize ) , 
80+             Ok ( read )  => Ok ( read as  usize ) , 
9181
9282            // The special treatment of BrokenPipe is to deal with Windows 
9383            // pipe semantics, which yields this error when *reading* from 
@@ -109,42 +99,23 @@ impl Handle {
10999    } 
110100
111101    pub  fn  read_at ( & self ,  buf :  & mut  [ u8 ] ,  offset :  u64 )  -> io:: Result < usize >  { 
112-         let  mut  read = 0 ; 
113-         let  len = cmp:: min ( buf. len ( ) ,  <c:: DWORD >:: MAX  as  usize )  as  c:: DWORD ; 
114-         let  res = unsafe  { 
115-             let  mut  overlapped:  c:: OVERLAPPED  = mem:: zeroed ( ) ; 
116-             overlapped. Offset  = offset as  u32 ; 
117-             overlapped. OffsetHigh  = ( offset >> 32 )  as  u32 ; 
118-             cvt ( c:: ReadFile ( 
119-                 self . as_handle ( ) , 
120-                 buf. as_mut_ptr ( )  as  c:: LPVOID , 
121-                 len, 
122-                 & mut  read, 
123-                 & mut  overlapped, 
124-             ) ) 
125-         } ; 
102+         let  res =
103+             unsafe  {  self . synchronous_read ( buf. as_mut_ptr ( ) . cast ( ) ,  buf. len ( ) ,  Some ( offset) )  } ; 
104+ 
126105        match  res { 
127-             Ok ( _ )  => Ok ( read as  usize ) , 
106+             Ok ( read )  => Ok ( read as  usize ) , 
128107            Err ( ref  e)  if  e. raw_os_error ( )  == Some ( c:: ERROR_HANDLE_EOF  as  i32 )  => Ok ( 0 ) , 
129108            Err ( e)  => Err ( e) , 
130109        } 
131110    } 
132111
133112    pub  fn  read_buf ( & self ,  buf :  & mut  ReadBuf < ' _ > )  -> io:: Result < ( ) >  { 
134-         let  mut  read = 0 ; 
135-         let  len = cmp:: min ( buf. remaining ( ) ,  <c:: DWORD >:: MAX  as  usize )  as  c:: DWORD ; 
136-         let  res = cvt ( unsafe  { 
137-             c:: ReadFile ( 
138-                 self . as_handle ( ) , 
139-                 buf. unfilled_mut ( ) . as_mut_ptr ( )  as  c:: LPVOID , 
140-                 len, 
141-                 & mut  read, 
142-                 ptr:: null_mut ( ) , 
143-             ) 
144-         } ) ; 
113+         let  res = unsafe  { 
114+             self . synchronous_read ( buf. unfilled_mut ( ) . as_mut_ptr ( ) ,  buf. remaining ( ) ,  None ) 
115+         } ; 
145116
146117        match  res { 
147-             Ok ( _ )  => { 
118+             Ok ( read )  => { 
148119                // Safety: `read` bytes were written to the initialized portion of the buffer 
149120                unsafe  { 
150121                    buf. assume_init ( read as  usize ) ; 
@@ -221,18 +192,7 @@ impl Handle {
221192    } 
222193
223194    pub  fn  write ( & self ,  buf :  & [ u8 ] )  -> io:: Result < usize >  { 
224-         let  mut  amt = 0 ; 
225-         let  len = cmp:: min ( buf. len ( ) ,  <c:: DWORD >:: MAX  as  usize )  as  c:: DWORD ; 
226-         cvt ( unsafe  { 
227-             c:: WriteFile ( 
228-                 self . as_handle ( ) , 
229-                 buf. as_ptr ( )  as  c:: LPVOID , 
230-                 len, 
231-                 & mut  amt, 
232-                 ptr:: null_mut ( ) , 
233-             ) 
234-         } ) ?; 
235-         Ok ( amt as  usize ) 
195+         unsafe  {  self . synchronous_write ( & buf,  None )  } 
236196    } 
237197
238198    pub  fn  write_vectored ( & self ,  bufs :  & [ IoSlice < ' _ > ] )  -> io:: Result < usize >  { 
@@ -245,21 +205,7 @@ impl Handle {
245205    } 
246206
247207    pub  fn  write_at ( & self ,  buf :  & [ u8 ] ,  offset :  u64 )  -> io:: Result < usize >  { 
248-         let  mut  written = 0 ; 
249-         let  len = cmp:: min ( buf. len ( ) ,  <c:: DWORD >:: MAX  as  usize )  as  c:: DWORD ; 
250-         unsafe  { 
251-             let  mut  overlapped:  c:: OVERLAPPED  = mem:: zeroed ( ) ; 
252-             overlapped. Offset  = offset as  u32 ; 
253-             overlapped. OffsetHigh  = ( offset >> 32 )  as  u32 ; 
254-             cvt ( c:: WriteFile ( 
255-                 self . as_handle ( ) , 
256-                 buf. as_ptr ( )  as  c:: LPVOID , 
257-                 len, 
258-                 & mut  written, 
259-                 & mut  overlapped, 
260-             ) ) ?; 
261-         } 
262-         Ok ( written as  usize ) 
208+         unsafe  {  self . synchronous_write ( & buf,  Some ( offset) )  } 
263209    } 
264210
265211    pub  fn  try_clone ( & self )  -> io:: Result < Self >  { 
@@ -274,6 +220,96 @@ impl Handle {
274220    )  -> io:: Result < Self >  { 
275221        Ok ( Self ( self . 0 . duplicate ( access,  inherit,  options) ?) ) 
276222    } 
223+ 
224+     /// Performs a synchronous read. 
225+      /// 
226+      /// If the handle is opened for asynchronous I/O then this abort the process. 
227+      /// See #81357. 
228+      /// 
229+      /// If `offset` is `None` then the current file position is used. 
230+      unsafe  fn  synchronous_read ( 
231+         & self , 
232+         buf :  * mut  mem:: MaybeUninit < u8 > , 
233+         len :  usize , 
234+         offset :  Option < u64 > , 
235+     )  -> io:: Result < usize >  { 
236+         let  mut  io_status = c:: IO_STATUS_BLOCK :: default ( ) ; 
237+ 
238+         // The length is clamped at u32::MAX. 
239+         let  len = cmp:: min ( len,  c:: DWORD :: MAX  as  usize )  as  c:: DWORD ; 
240+         let  status = c:: NtReadFile ( 
241+             self . as_handle ( ) , 
242+             ptr:: null_mut ( ) , 
243+             None , 
244+             ptr:: null_mut ( ) , 
245+             & mut  io_status, 
246+             buf, 
247+             len, 
248+             offset. map ( |n| n as  _ ) . as_ref ( ) , 
249+             None , 
250+         ) ; 
251+         match  status { 
252+             // If the operation has not completed then abort the process. 
253+             // Doing otherwise means that the buffer and stack may be written to 
254+             // after this function returns. 
255+             c:: STATUS_PENDING  => { 
256+                 eprintln ! ( "I/O error: operation failed to complete synchronously" ) ; 
257+                 crate :: process:: abort ( ) ; 
258+             } 
259+ 
260+             // Return `Ok(0)` when there's nothing more to read. 
261+             c:: STATUS_END_OF_FILE  => Ok ( 0 ) , 
262+ 
263+             // Success! 
264+             status if  c:: nt_success ( status)  => Ok ( io_status. Information ) , 
265+ 
266+             status => { 
267+                 let  error = c:: RtlNtStatusToDosError ( status) ; 
268+                 Err ( io:: Error :: from_raw_os_error ( error as  _ ) ) 
269+             } 
270+         } 
271+     } 
272+ 
273+     /// Performs a synchronous write. 
274+      /// 
275+      /// If the handle is opened for asynchronous I/O then this abort the process. 
276+      /// See #81357. 
277+      /// 
278+      /// If `offset` is `None` then the current file position is used. 
279+      unsafe  fn  synchronous_write ( & self ,  buf :  & [ u8 ] ,  offset :  Option < u64 > )  -> io:: Result < usize >  { 
280+         let  mut  io_status = c:: IO_STATUS_BLOCK :: default ( ) ; 
281+ 
282+         // The length is clamped at u32::MAX. 
283+         let  len = cmp:: min ( buf. len ( ) ,  c:: DWORD :: MAX  as  usize )  as  c:: DWORD ; 
284+         let  status = c:: NtWriteFile ( 
285+             self . as_handle ( ) , 
286+             ptr:: null_mut ( ) , 
287+             None , 
288+             ptr:: null_mut ( ) , 
289+             & mut  io_status, 
290+             buf. as_ptr ( ) , 
291+             len, 
292+             offset. map ( |n| n as  _ ) . as_ref ( ) , 
293+             None , 
294+         ) ; 
295+         match  status { 
296+             // If the operation has not completed then abort the process. 
297+             // Doing otherwise means that the buffer maybe read and the stack 
298+             // written to after this function returns. 
299+             c:: STATUS_PENDING  => { 
300+                 eprintln ! ( "I/O error: operation failed to complete synchronously" ) ; 
301+                 crate :: process:: abort ( ) ; 
302+             } 
303+ 
304+             // Success! 
305+             status if  c:: nt_success ( status)  => Ok ( io_status. Information ) , 
306+ 
307+             status => { 
308+                 let  error = c:: RtlNtStatusToDosError ( status) ; 
309+                 Err ( io:: Error :: from_raw_os_error ( error as  _ ) ) 
310+             } 
311+         } 
312+     } 
277313} 
278314
279315impl < ' a >  Read  for  & ' a  Handle  { 
0 commit comments