2
2
//@compile-flags: -Zmiri-disable-isolation
3
3
#![ allow( nonstandard_style) ]
4
4
5
- use std:: io:: { ErrorKind , Read , Write } ;
5
+ use std:: io:: { ErrorKind , Read , Seek , SeekFrom , Write } ;
6
6
use std:: os:: windows:: ffi:: OsStrExt ;
7
- use std:: os:: windows:: io:: AsRawHandle ;
7
+ use std:: os:: windows:: io:: { AsRawHandle , FromRawHandle } ;
8
8
use std:: path:: Path ;
9
- use std:: { fs, ptr} ;
9
+ use std:: { fs, mem , ptr} ;
10
10
11
11
#[ path = "../../utils/mod.rs" ]
12
12
mod utils;
13
13
14
14
use windows_sys:: Wdk :: Storage :: FileSystem :: { NtReadFile , NtWriteFile } ;
15
15
use windows_sys:: Win32 :: Foundation :: {
16
- CloseHandle , ERROR_ACCESS_DENIED , ERROR_ALREADY_EXISTS , ERROR_IO_DEVICE , GENERIC_READ ,
17
- GENERIC_WRITE , GetLastError , RtlNtStatusToDosError , STATUS_ACCESS_DENIED ,
18
- STATUS_IO_DEVICE_ERROR , STATUS_SUCCESS , SetLastError ,
16
+ CloseHandle , DUPLICATE_SAME_ACCESS , DuplicateHandle , ERROR_ACCESS_DENIED , ERROR_ALREADY_EXISTS ,
17
+ ERROR_IO_DEVICE , FALSE , GENERIC_READ , GENERIC_WRITE , GetLastError , RtlNtStatusToDosError ,
18
+ STATUS_ACCESS_DENIED , STATUS_IO_DEVICE_ERROR , STATUS_SUCCESS , SetLastError ,
19
19
} ;
20
20
use windows_sys:: Win32 :: Storage :: FileSystem :: {
21
21
BY_HANDLE_FILE_INFORMATION , CREATE_ALWAYS , CREATE_NEW , CreateFileW , DeleteFileW ,
@@ -24,6 +24,7 @@ use windows_sys::Win32::Storage::FileSystem::{
24
24
FILE_SHARE_WRITE , GetFileInformationByHandle , OPEN_ALWAYS , OPEN_EXISTING , SetFilePointerEx ,
25
25
} ;
26
26
use windows_sys:: Win32 :: System :: IO :: IO_STATUS_BLOCK ;
27
+ use windows_sys:: Win32 :: System :: Threading :: GetCurrentProcess ;
27
28
28
29
fn main ( ) {
29
30
unsafe {
@@ -36,6 +37,7 @@ fn main() {
36
37
test_ntstatus_to_dos ( ) ;
37
38
test_file_read_write ( ) ;
38
39
test_file_seek ( ) ;
40
+ test_dup_handle ( ) ;
39
41
}
40
42
}
41
43
@@ -273,6 +275,39 @@ unsafe fn test_file_read_write() {
273
275
assert_eq ! ( GetLastError ( ) , 1234 ) ;
274
276
}
275
277
278
+ unsafe fn test_dup_handle ( ) {
279
+ let temp = utils:: tmp ( ) . join ( "test_dup.txt" ) ;
280
+
281
+ let mut file1 = fs:: File :: options ( ) . read ( true ) . write ( true ) . create ( true ) . open ( & temp) . unwrap ( ) ;
282
+
283
+ file1. write_all ( b"Hello, World!\n " ) . unwrap ( ) ;
284
+ file1. seek ( SeekFrom :: Start ( 0 ) ) . unwrap ( ) ;
285
+
286
+ let first_handle = file1. as_raw_handle ( ) ;
287
+
288
+ let cur_proc = GetCurrentProcess ( ) ;
289
+ let mut second_handle = mem:: zeroed ( ) ;
290
+ let res = DuplicateHandle (
291
+ cur_proc,
292
+ first_handle,
293
+ cur_proc,
294
+ & mut second_handle,
295
+ 0 ,
296
+ FALSE ,
297
+ DUPLICATE_SAME_ACCESS ,
298
+ ) ;
299
+ assert ! ( res != 0 ) ;
300
+
301
+ let mut buf1 = [ 0 ; 5 ] ;
302
+ file1. read ( & mut buf1) . unwrap ( ) ;
303
+ assert_eq ! ( & buf1, b"Hello" ) ;
304
+
305
+ let mut file2 = fs:: File :: from_raw_handle ( second_handle) ;
306
+ let mut buf2 = [ 0 ; 5 ] ;
307
+ file2. read ( & mut buf2) . unwrap ( ) ;
308
+ assert_eq ! ( & buf2, b", Wor" ) ;
309
+ }
310
+
276
311
unsafe fn test_file_seek ( ) {
277
312
let temp = utils:: tmp ( ) . join ( "test_file_seek.txt" ) ;
278
313
let mut file = fs:: File :: options ( ) . create ( true ) . write ( true ) . read ( true ) . open ( & temp) . unwrap ( ) ;
0 commit comments