mirror of
https://github.com/reactos/reactos.git
synced 2025-06-05 09:20:30 +00:00
96 lines
2.7 KiB
C++
96 lines
2.7 KiB
C++
//
|
|
// dup.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Defines _dup() and _dup_nolock, which duplicate lowio file handles
|
|
//
|
|
#include <corecrt_internal_lowio.h>
|
|
#include <corecrt_internal_ptd_propagation.h>
|
|
|
|
static int __cdecl duplicate_osfhnd(int const fh, int const new_fh, __crt_cached_ptd_host& ptd) throw()
|
|
{
|
|
// Duplicate the file handle:
|
|
intptr_t new_osfhandle;
|
|
|
|
BOOL const result = DuplicateHandle(
|
|
GetCurrentProcess(),
|
|
reinterpret_cast<HANDLE>(_get_osfhandle(fh)),
|
|
GetCurrentProcess(),
|
|
&reinterpret_cast<HANDLE&>(new_osfhandle),
|
|
0L,
|
|
TRUE,
|
|
DUPLICATE_SAME_ACCESS);
|
|
|
|
if (!result)
|
|
{
|
|
__acrt_errno_map_os_error_ptd(GetLastError(), ptd);
|
|
return -1;
|
|
}
|
|
|
|
// Duplicate the handle state:
|
|
__acrt_lowio_set_os_handle(new_fh, new_osfhandle);
|
|
_osfile(new_fh) = _osfile(fh) & ~FNOINHERIT;
|
|
_textmode(new_fh) = _textmode(fh);
|
|
_tm_unicode(new_fh) = _tm_unicode(fh);
|
|
return new_fh;
|
|
}
|
|
|
|
static int __cdecl _dup_nolock_internal(int const fh, __crt_cached_ptd_host& ptd) throw()
|
|
{
|
|
if ((_osfile(fh) & FOPEN) == 0)
|
|
{
|
|
ptd.get_errno().set(EBADF);
|
|
ptd.get_doserrno().set(0);
|
|
_ASSERTE(("Invalid file descriptor. File possibly closed by a different thread", 0));
|
|
return -1;
|
|
}
|
|
|
|
// Allocate a duplicate handle
|
|
int const new_fh = _alloc_osfhnd();
|
|
if (new_fh == -1)
|
|
{
|
|
ptd.get_errno().set(EMFILE);
|
|
ptd.get_doserrno().set(0);
|
|
return -1;
|
|
}
|
|
|
|
int return_value = -1;
|
|
__try
|
|
{
|
|
return_value = duplicate_osfhnd(fh, new_fh, ptd);
|
|
}
|
|
__finally
|
|
{
|
|
// The handle returned by _alloc_osfhnd is both open and locked. If we
|
|
// failed to duplicate the handle, we need to abandon the handle by
|
|
// unsetting the open flag. We always need to unlock the handle:
|
|
if (return_value == -1)
|
|
{
|
|
_osfile(new_fh) &= ~FOPEN;
|
|
}
|
|
|
|
__acrt_lowio_unlock_fh(new_fh);
|
|
}
|
|
__endtry
|
|
return return_value;
|
|
}
|
|
|
|
static int __cdecl _dup_internal(int const fh, __crt_cached_ptd_host& ptd)
|
|
{
|
|
_UCRT_CHECK_FH_CLEAR_OSSERR_RETURN(ptd, fh, EBADF, -1);
|
|
_UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, (fh >= 0 && (unsigned)fh < (unsigned)_nhandle), EBADF, -1);
|
|
_UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, (_osfile(fh) & FOPEN), EBADF, -1);
|
|
|
|
return __acrt_lowio_lock_fh_and_call(fh, [&](){
|
|
return _dup_nolock_internal(fh, ptd);
|
|
});
|
|
}
|
|
|
|
// _dup() duplicates a file handle and returns the duplicate. If the function
|
|
// fails, -1 is returned and errno is set.
|
|
extern "C" int __cdecl _dup(int const fh)
|
|
{
|
|
__crt_cached_ptd_host ptd;
|
|
return _dup_internal(fh, ptd);
|
|
}
|