Reactos
at master 96 lines 2.8 kB view raw
1// 2// dup.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines _dup() and _dup_nolock, which duplicate lowio file handles 7// 8#include <corecrt_internal_lowio.h> 9#include <corecrt_internal_ptd_propagation.h> 10 11static int __cdecl duplicate_osfhnd(int const fh, int const new_fh, __crt_cached_ptd_host& ptd) throw() 12{ 13 // Duplicate the file handle: 14 intptr_t new_osfhandle; 15 16 BOOL const result = DuplicateHandle( 17 GetCurrentProcess(), 18 reinterpret_cast<HANDLE>(_get_osfhandle(fh)), 19 GetCurrentProcess(), 20 &reinterpret_cast<HANDLE&>(new_osfhandle), 21 0L, 22 TRUE, 23 DUPLICATE_SAME_ACCESS); 24 25 if (!result) 26 { 27 __acrt_errno_map_os_error_ptd(GetLastError(), ptd); 28 return -1; 29 } 30 31 // Duplicate the handle state: 32 __acrt_lowio_set_os_handle(new_fh, new_osfhandle); 33 _osfile(new_fh) = _osfile(fh) & ~FNOINHERIT; 34 _textmode(new_fh) = _textmode(fh); 35 _tm_unicode(new_fh) = _tm_unicode(fh); 36 return new_fh; 37} 38 39static int __cdecl _dup_nolock_internal(int const fh, __crt_cached_ptd_host& ptd) throw() 40{ 41 if ((_osfile(fh) & FOPEN) == 0) 42 { 43 ptd.get_errno().set(EBADF); 44 ptd.get_doserrno().set(0); 45 _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread", 0)); 46 return -1; 47 } 48 49 // Allocate a duplicate handle 50 int const new_fh = _alloc_osfhnd(); 51 if (new_fh == -1) 52 { 53 ptd.get_errno().set(EMFILE); 54 ptd.get_doserrno().set(0); 55 return -1; 56 } 57 58 int return_value = -1; 59 __try 60 { 61 return_value = duplicate_osfhnd(fh, new_fh, ptd); 62 } 63 __finally 64 { 65 // The handle returned by _alloc_osfhnd is both open and locked. If we 66 // failed to duplicate the handle, we need to abandon the handle by 67 // unsetting the open flag. We always need to unlock the handle: 68 if (return_value == -1) 69 { 70 _osfile(new_fh) &= ~FOPEN; 71 } 72 73 __acrt_lowio_unlock_fh(new_fh); 74 } 75 __endtry 76 return return_value; 77} 78 79static int __cdecl _dup_internal(int const fh, __crt_cached_ptd_host& ptd) 80{ 81 _UCRT_CHECK_FH_CLEAR_OSSERR_RETURN(ptd, fh, EBADF, -1); 82 _UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, (fh >= 0 && (unsigned)fh < (unsigned)_nhandle), EBADF, -1); 83 _UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, (_osfile(fh) & FOPEN), EBADF, -1); 84 85 return __acrt_lowio_lock_fh_and_call(fh, [&](){ 86 return _dup_nolock_internal(fh, ptd); 87 }); 88} 89 90// _dup() duplicates a file handle and returns the duplicate. If the function 91// fails, -1 is returned and errno is set. 92extern "C" int __cdecl _dup(int const fh) 93{ 94 __crt_cached_ptd_host ptd; 95 return _dup_internal(fh, ptd); 96}