@@ -7,7 +7,7 @@ use crate::fmt;
77use crate :: fs;
88use crate :: io;
99use crate :: marker:: PhantomData ;
10- use crate :: mem:: forget;
10+ use crate :: mem:: { forget, ManuallyDrop } ;
1111use crate :: ptr;
1212use crate :: sys;
1313use crate :: sys:: cvt;
@@ -91,7 +91,7 @@ pub struct OwnedHandle {
9191#[ repr( transparent) ]
9292#[ stable( feature = "io_safety" , since = "1.63.0" ) ]
9393#[ derive( Debug ) ]
94- pub struct HandleOrNull ( OwnedHandle ) ;
94+ pub struct HandleOrNull ( RawHandle ) ;
9595
9696/// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
9797/// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
@@ -110,7 +110,7 @@ pub struct HandleOrNull(OwnedHandle);
110110#[ repr( transparent) ]
111111#[ stable( feature = "io_safety" , since = "1.63.0" ) ]
112112#[ derive( Debug ) ]
113- pub struct HandleOrInvalid ( OwnedHandle ) ;
113+ pub struct HandleOrInvalid ( RawHandle ) ;
114114
115115// The Windows [`HANDLE`] type may be transferred across and shared between
116116// thread boundaries (despite containing a `*mut void`, which in general isn't
@@ -163,15 +163,24 @@ impl TryFrom<HandleOrNull> for OwnedHandle {
163163
164164 #[ inline]
165165 fn try_from ( handle_or_null : HandleOrNull ) -> Result < Self , NullHandleError > {
166- let owned_handle = handle_or_null. 0 ;
167- if owned_handle. handle . is_null ( ) {
168- // Don't call `CloseHandle`; it'd be harmless, except that it could
169- // overwrite the `GetLastError` error.
170- forget ( owned_handle) ;
171-
172- Err ( NullHandleError ( ( ) ) )
166+ let handle_or_null = ManuallyDrop :: new ( handle_or_null) ;
167+ if handle_or_null. is_valid ( ) {
168+ // SAFETY: The handle is not null.
169+ Ok ( unsafe { OwnedHandle :: from_raw_handle ( handle_or_null. 0 ) } )
173170 } else {
174- Ok ( owned_handle)
171+ Err ( NullHandleError ( ( ) ) )
172+ }
173+ }
174+ }
175+
176+ #[ stable( feature = "io_safety" , since = "1.63.0" ) ]
177+ impl Drop for HandleOrNull {
178+ #[ inline]
179+ fn drop ( & mut self ) {
180+ if self . is_valid ( ) {
181+ unsafe {
182+ let _ = sys:: c:: CloseHandle ( self . 0 ) ;
183+ }
175184 }
176185 }
177186}
@@ -232,15 +241,24 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {
232241
233242 #[ inline]
234243 fn try_from ( handle_or_invalid : HandleOrInvalid ) -> Result < Self , InvalidHandleError > {
235- let owned_handle = handle_or_invalid. 0 ;
236- if owned_handle. handle == sys:: c:: INVALID_HANDLE_VALUE {
237- // Don't call `CloseHandle`; it'd be harmless, except that it could
238- // overwrite the `GetLastError` error.
239- forget ( owned_handle) ;
240-
241- Err ( InvalidHandleError ( ( ) ) )
244+ let handle_or_invalid = ManuallyDrop :: new ( handle_or_invalid) ;
245+ if handle_or_invalid. is_valid ( ) {
246+ // SAFETY: The handle is not invalid.
247+ Ok ( unsafe { OwnedHandle :: from_raw_handle ( handle_or_invalid. 0 ) } )
242248 } else {
243- Ok ( owned_handle)
249+ Err ( InvalidHandleError ( ( ) ) )
250+ }
251+ }
252+ }
253+
254+ #[ stable( feature = "io_safety" , since = "1.63.0" ) ]
255+ impl Drop for HandleOrInvalid {
256+ #[ inline]
257+ fn drop ( & mut self ) {
258+ if self . is_valid ( ) {
259+ unsafe {
260+ let _ = sys:: c:: CloseHandle ( self . 0 ) ;
261+ }
244262 }
245263 }
246264}
@@ -333,7 +351,11 @@ impl HandleOrNull {
333351 #[ stable( feature = "io_safety" , since = "1.63.0" ) ]
334352 #[ inline]
335353 pub unsafe fn from_raw_handle ( handle : RawHandle ) -> Self {
336- Self ( OwnedHandle :: from_raw_handle ( handle) )
354+ Self ( handle)
355+ }
356+
357+ fn is_valid ( & self ) -> bool {
358+ !self . 0 . is_null ( )
337359 }
338360}
339361
@@ -356,7 +378,11 @@ impl HandleOrInvalid {
356378 #[ stable( feature = "io_safety" , since = "1.63.0" ) ]
357379 #[ inline]
358380 pub unsafe fn from_raw_handle ( handle : RawHandle ) -> Self {
359- Self ( OwnedHandle :: from_raw_handle ( handle) )
381+ Self ( handle)
382+ }
383+
384+ fn is_valid ( & self ) -> bool {
385+ self . 0 != sys:: c:: INVALID_HANDLE_VALUE
360386 }
361387}
362388
0 commit comments