本文整理汇总了C++中HandleTable类的典型用法代码示例。如果您正苦于以下问题:C++ HandleTable类的具体用法?C++ HandleTable怎么用?C++ HandleTable使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了HandleTable类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: ASSERT_MSG
namespace Kernel {
unsigned int Object::next_object_id;
HandleTable g_handle_table;
void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
waiting_threads.push_back(std::move(thread));
}
void WaitObject::RemoveWaitingThread(Thread* thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr != waiting_threads.end())
waiting_threads.erase(itr);
}
SharedPtr<Thread> WaitObject::WakeupNextThread() {
if (waiting_threads.empty())
return nullptr;
auto next_thread = std::move(waiting_threads.front());
waiting_threads.erase(waiting_threads.begin());
next_thread->ReleaseWaitObject(this);
return next_thread;
}
void WaitObject::WakeupAllWaitingThreads() {
auto waiting_threads_copy = waiting_threads;
// We use a copy because ReleaseWaitObject will remove the thread from this object's
// waiting_threads list
for (auto thread : waiting_threads_copy)
thread->ReleaseWaitObject(this);
ASSERT_MSG(waiting_threads.empty(), "failed to awaken all waiting threads!");
}
HandleTable::HandleTable() {
next_generation = 1;
Clear();
}
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
DEBUG_ASSERT(obj != nullptr);
u16 slot = next_free_slot;
if (slot >= generations.size()) {
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
return ERR_OUT_OF_HANDLES;
}
next_free_slot = generations[slot];
u16 generation = next_generation++;
// Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
// CTR-OS doesn't use generation 0, so skip straight to 1.
if (next_generation >= (1 << 15)) next_generation = 1;
generations[slot] = generation;
objects[slot] = std::move(obj);
Handle handle = generation | (slot << 15);
return MakeResult<Handle>(handle);
}
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
SharedPtr<Object> object = GetGeneric(handle);
if (object == nullptr) {
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
return ERR_INVALID_HANDLE;
}
return Create(std::move(object));
}
ResultCode HandleTable::Close(Handle handle) {
if (!IsValid(handle))
return ERR_INVALID_HANDLE;
u16 slot = GetSlot(handle);
objects[slot] = nullptr;
generations[slot] = next_free_slot;
next_free_slot = slot;
return RESULT_SUCCESS;
}
bool HandleTable::IsValid(Handle handle) const {
size_t slot = GetSlot(handle);
u16 generation = GetGeneration(handle);
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
}
SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
if (handle == CurrentThread) {
return GetCurrentThread();
//.........这里部分代码省略.........
示例2: LUA_START_VALIDATE
dmz::Handle *
dmz::lua_create_handle (lua_State *L, const Handle Value) {
LUA_START_VALIDATE (L);
Handle *result = 0;
if (Value) {
HandleTable *ht (get_handle_table (L));
lua_pushlightuserdata (L, (void *)&LuaHandleTableKey);
lua_rawget (L, LUA_REGISTRYINDEX);
const int Table (lua_gettop (L));
if (lua_istable (L, Table) && ht) {
int *indexPtr = ht->lookup (Value);
if (indexPtr) {
lua_rawgeti (L, Table, *indexPtr);
result = (Handle *)lua_touserdata (L, -1);
if (!result) { lua_pop (L, 1); }
else if (*result != Value) {
lua_pop (L, 1); // pop invalid Handle;
result = 0;
}
}
if (!result) {
if (indexPtr && ht->remove (Value)) { delete indexPtr; indexPtr = 0; }
result = (Handle *)lua_newuserdata (L, sizeof (Handle));
if (result) {
lua_pushvalue (L, -1);
int index = luaL_ref (L, Table);
indexPtr = new int (index);
if (!ht->store (Value, indexPtr)) { delete indexPtr; indexPtr = 0; }
*result = Value;
luaL_getmetatable (L, HandleName);
lua_setmetatable (L, -2);
}
}
}
lua_remove (L, Table); // Remove Table;
}
if (!result) { lua_pushnil (L); }
LUA_END_VALIDATE (L, 1);
return result;
}
示例3: _assert_msg_
namespace Kernel {
SharedPtr<Thread> g_main_thread = nullptr;
HandleTable g_handle_table;
u64 g_program_id = 0;
void WaitObject::AddWaitingThread(Thread* thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
waiting_threads.push_back(thread);
}
void WaitObject::RemoveWaitingThread(Thread* thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr != waiting_threads.end())
waiting_threads.erase(itr);
}
Thread* WaitObject::WakeupNextThread() {
if (waiting_threads.empty())
return nullptr;
auto next_thread = waiting_threads.front();
waiting_threads.erase(waiting_threads.begin());
next_thread->ReleaseWaitObject(this);
return next_thread;
}
void WaitObject::WakeupAllWaitingThreads() {
auto waiting_threads_copy = waiting_threads;
// We use a copy because ReleaseWaitObject will remove the thread from this object's
// waiting_threads list
for (auto thread : waiting_threads_copy)
thread->ReleaseWaitObject(this);
_assert_msg_(Kernel, waiting_threads.empty(), "failed to awaken all waiting threads!");
}
HandleTable::HandleTable() {
next_generation = 1;
Clear();
}
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
_dbg_assert_(Kernel, obj != nullptr);
u16 slot = next_free_slot;
if (slot >= generations.size()) {
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
return ERR_OUT_OF_HANDLES;
}
next_free_slot = generations[slot];
u16 generation = next_generation++;
// Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
// CTR-OS doesn't use generation 0, so skip straight to 1.
if (next_generation >= (1 << 15)) next_generation = 1;
Handle handle = generation | (slot << 15);
if (obj->handle == INVALID_HANDLE)
obj->handle = handle;
generations[slot] = generation;
objects[slot] = std::move(obj);
return MakeResult<Handle>(handle);
}
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
SharedPtr<Object> object = GetGeneric(handle);
if (object == nullptr) {
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
return ERR_INVALID_HANDLE;
}
return Create(std::move(object));
}
ResultCode HandleTable::Close(Handle handle) {
if (!IsValid(handle))
return ERR_INVALID_HANDLE;
size_t slot = GetSlot(handle);
u16 generation = GetGeneration(handle);
objects[slot] = nullptr;
generations[generation] = next_free_slot;
next_free_slot = slot;
return RESULT_SUCCESS;
}
bool HandleTable::IsValid(Handle handle) const {
size_t slot = GetSlot(handle);
u16 generation = GetGeneration(handle);
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
//.........这里部分代码省略.........
示例4: PopulateFromIncomingCommandBuffer
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf,
Process& src_process,
HandleTable& src_table) {
IPC::Header header{src_cmdbuf[0]};
size_t untranslated_size = 1u + header.normal_params_size;
size_t command_size = untranslated_size + header.translate_params_size;
ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH); // TODO(yuriks): Return error
std::copy_n(src_cmdbuf, untranslated_size, cmd_buf.begin());
size_t i = untranslated_size;
while (i < command_size) {
u32 descriptor = cmd_buf[i] = src_cmdbuf[i];
i += 1;
switch (IPC::GetDescriptorType(descriptor)) {
case IPC::DescriptorType::CopyHandle:
case IPC::DescriptorType::MoveHandle: {
u32 num_handles = IPC::HandleNumberFromDesc(descriptor);
ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error
for (u32 j = 0; j < num_handles; ++j) {
Handle handle = src_cmdbuf[i];
SharedPtr<Object> object = nullptr;
if (handle != 0) {
object = src_table.GetGeneric(handle);
ASSERT(object != nullptr); // TODO(yuriks): Return error
if (descriptor == IPC::DescriptorType::MoveHandle) {
src_table.Close(handle);
}
}
cmd_buf[i++] = AddOutgoingHandle(std::move(object));
}
break;
}
case IPC::DescriptorType::CallingPid: {
cmd_buf[i++] = src_process.process_id;
break;
}
case IPC::DescriptorType::StaticBuffer: {
VAddr source_address = src_cmdbuf[i];
IPC::StaticBufferDescInfo buffer_info{descriptor};
// Copy the input buffer into our own vector and store it.
std::vector<u8> data(buffer_info.size);
Memory::ReadBlock(src_process, source_address, data.data(), data.size());
AddStaticBuffer(buffer_info.buffer_id, std::move(data));
cmd_buf[i++] = source_address;
break;
}
case IPC::DescriptorType::MappedBuffer: {
u32 next_id = static_cast<u32>(request_mapped_buffers.size());
request_mapped_buffers.emplace_back(src_process, descriptor, src_cmdbuf[i], next_id);
cmd_buf[i++] = next_id;
break;
}
default:
UNIMPLEMENTED_MSG("Unsupported handle translation: {:#010X}", descriptor);
}
}
return RESULT_SUCCESS;
}
示例5: WriteToOutgoingCommandBuffer
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
HandleTable& dst_table) const {
IPC::Header header{cmd_buf[0]};
size_t untranslated_size = 1u + header.normal_params_size;
size_t command_size = untranslated_size + header.translate_params_size;
ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH);
std::copy_n(cmd_buf.begin(), untranslated_size, dst_cmdbuf);
size_t i = untranslated_size;
while (i < command_size) {
u32 descriptor = dst_cmdbuf[i] = cmd_buf[i];
i += 1;
switch (IPC::GetDescriptorType(descriptor)) {
case IPC::DescriptorType::CopyHandle:
case IPC::DescriptorType::MoveHandle: {
// HLE services don't use handles, so we treat both CopyHandle and MoveHandle equally
u32 num_handles = IPC::HandleNumberFromDesc(descriptor);
ASSERT(i + num_handles <= command_size);
for (u32 j = 0; j < num_handles; ++j) {
SharedPtr<Object> object = GetIncomingHandle(cmd_buf[i]);
Handle handle = 0;
if (object != nullptr) {
// TODO(yuriks): Figure out the proper error handling for if this fails
handle = dst_table.Create(object).Unwrap();
}
dst_cmdbuf[i++] = handle;
}
break;
}
case IPC::DescriptorType::StaticBuffer: {
IPC::StaticBufferDescInfo buffer_info{descriptor};
const auto& data = GetStaticBuffer(buffer_info.buffer_id);
// Grab the address that the target thread set up to receive the response static buffer
// and write our data there. The static buffers area is located right after the command
// buffer area.
size_t static_buffer_offset = IPC::COMMAND_BUFFER_LENGTH + 2 * buffer_info.buffer_id;
IPC::StaticBufferDescInfo target_descriptor{dst_cmdbuf[static_buffer_offset]};
VAddr target_address = dst_cmdbuf[static_buffer_offset + 1];
ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big");
Memory::WriteBlock(dst_process, target_address, data.data(), data.size());
dst_cmdbuf[i++] = target_address;
break;
}
case IPC::DescriptorType::MappedBuffer: {
VAddr addr = request_mapped_buffers[cmd_buf[i]].address;
dst_cmdbuf[i++] = addr;
break;
}
default:
UNIMPLEMENTED_MSG("Unsupported handle translation: {:#010X}", descriptor);
}
}
return RESULT_SUCCESS;
}
示例6: DosSetFHState
APIRET os2APIENTRY DosSetFHState(os2HFILE hFile,
ULONG mode)
{
if(mode&0x077f)
return 1; //FixMe: invalid flags
APIRET rc;
int idx=(int)hFile;
FileTable.lock(idx);
if(FileTable[idx]) {
ULONG oldmode = FileTable[idx]->mode;
ULONG newmode = (FileTable[idx]->mode&0x077f)|mode;
if((oldmode&OPEN_FLAGS_NOINHERIT)!=(newmode&OPEN_FLAGS_NOINHERIT)) {
//inheritance changed - duplicate and change
HANDLE target;
if(DuplicateHandle(GetCurrentProcess(),
FileTable[idx]->ntFileHandle,
GetCurrentProcess(),
&target,
0,
newmode&OPEN_FLAGS_NOINHERIT?FALSE:TRUE,
DUPLICATE_SAME_ACCESS
))
{
CloseHandle(FileTable[idx]->ntFileHandle);
FileTable[idx]->ntFileHandle = target;
} else
rc = (APIRET)GetLastError();
} else
rc = 0;
FileTable[idx]->mode = newmode;
} else
rc = 6; //invalid handle
FileTable.unlock(idx);
return rc;
}
示例7: DosSetFilePtr
APIRET os2APIENTRY DosSetFilePtr(os2HFILE hFile,
LONG ib,
ULONG method,
PULONG ibActual)
{
int idx=(int)hFile;
FileTable.lock(idx);
if(FileTable[idx]) {
FileTable.unlock(idx);
HANDLE hf=FileTable[idx]->ntFileHandle;
DWORD dw = SetFilePointer(hf,
(DWORD)ib,
0,
(LONG)method
);
if(dw==(DWORD)-1)
return (APIRET)GetLastError();
else {
*ibActual = (ULONG)dw;
return 0;
}
} else {
FileTable.unlock(idx);
return 6; //invalid handle
}
}
示例8: DosQueryHType
APIRET os2APIENTRY DosQueryHType(os2HFILE hFile,
PULONG pType,
PULONG pAttr)
{
int idx=(int)hFile;
FileTable.lock(idx);
if(FileTable[idx]) {
HANDLE hf=FileTable[idx]->ntFileHandle;
FileTable.unlock(idx);
DWORD t=GetFileType(hf);
*pType = 0;
switch(t) {
case FILE_TYPE_DISK: *pType = 0; break;
case FILE_TYPE_CHAR: *pType = 1; break;
case FILE_TYPE_PIPE: *pType = 2; break;
case FILE_TYPE_UNKNOWN:
default:
*pType = 3;
}
//We always set the network bit because we cannot retrieve device attributes
*pType |= 0x80;
*pAttr = 0;
return 0;
} else {
FileTable.unlock(idx);
return 6; //invalid handle
}
}
示例9: DosSetFileInfo
APIRET os2APIENTRY DosSetFileInfo(os2HFILE hFile,
ULONG ulInfoLevel,
PVOID pInfoBuf,
ULONG cbInfoBuf)
{
if(ulInfoLevel!=FIL_STANDARD &&
ulInfoLevel!=FIL_QUERYEASIZE)
return 124; //invalid level
APIRET rc;
int idx=(int)hFile;
FileTable.lock(idx);
if(!FileTable[idx]) {
rc = 6; //invalid handle
goto done;
}
if(ulInfoLevel==FIL_STANDARD) {
FILESTATUS3 *fs3=(FILESTATUS3*)pInfoBuf;
FILETIME *lpftCreation=0; FILETIME ftCreation;
FILETIME *lpftLastAccess=0; FILETIME ftLastAccess;
FILETIME *lpftLastWrite=0; FILETIME ftLastWrite;
if(cbInfoBuf>offsetof(FILESTATUS3,ftimeCreation) &&
(*(USHORT*)(&fs3->fdateCreation)!=0 || *(USHORT*)(&fs3->ftimeCreation)!=0))
{
os22ntfiletime(fs3->fdateCreation,fs3->ftimeCreation,&ftCreation);
lpftCreation=&ftCreation;
}
if(cbInfoBuf>offsetof(FILESTATUS3,ftimeLastAccess) &&
(*(USHORT*)(&fs3->fdateLastAccess)!=0 || *(USHORT*)(&fs3->ftimeLastAccess)!=0))
{
os22ntfiletime(fs3->fdateLastAccess,fs3->ftimeCreation,&ftLastAccess);
lpftLastAccess=&ftLastAccess;
}
if(cbInfoBuf>offsetof(FILESTATUS3,ftimeLastWrite) &&
(*(USHORT*)(&fs3->fdateLastWrite)!=0 || *(USHORT*)(&fs3->ftimeLastWrite)!=0))
{
os22ntfiletime(fs3->fdateLastWrite,fs3->ftimeCreation,&ftLastWrite);
lpftLastWrite=&ftLastWrite;
}
if(!SetFileTime(FileTable[idx]->ntFileHandle,
lpftCreation,
lpftLastAccess,
lpftLastWrite
)) {
rc = (APIRET)GetLastError();
goto done;
}
//attributes cannot be changed
rc = 0;
}
done:
FileTable.unlock(idx);
return rc;
}
示例10: DosCreatePipe
APIRET os2APIENTRY DosCreatePipe(PHFILE phfRead,
PHFILE phfWrite,
ULONG cb)
{
if(phfRead==0 || phfWrite==0)
return 87; //invalid parameter
ntFILE *ntFileR=new ntFILE;
if(!ntFileR) return 8; //not enough memory
ntFILE *ntFileW=new ntFILE;
if(!ntFileW) {
delete ntFileR;
return 8; //not enough memory
}
int idxR=FileTable.findAndLockFree();
if(idxR==-1) {
delete ntFileR;
delete ntFileW;
return 4; //too many open files
}
int idxW=FileTable.findAndLockFree();
if(idxW==-1) {
delete ntFileR;
delete ntFileW;
FileTable.unlock(idxR);
return 4; //too many open files
}
HANDLE hReadPipe,hWritePipe;
SECURITY_ATTRIBUTES sa;
memset(&sa,0,sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE; //os/2 pipes are by default inherited, nt pipes isn't
if(CreatePipe(&hReadPipe,&hWritePipe,&sa,(DWORD)cb)) {
ntFileR->ntFileHandle = hReadPipe;
ntFileR->mode = OPEN_ACCESS_READONLY;
ntFileW->ntFileHandle = hWritePipe;
ntFileW->mode = OPEN_ACCESS_WRITEONLY;
FileTable[idxR] = ntFileR;
FileTable[idxW] = ntFileW;
FileTable.unlock(idxR);
FileTable.unlock(idxW);
*phfRead = (os2HFILE)idxR;
*phfWrite = (os2HFILE)idxW;
return 0;
} else {
FileTable.unlock(idxR);
FileTable.unlock(idxW);
delete ntFileR;
delete ntFileW;
return (APIRET)GetLastError();
}
}
示例11: DosQueryFHState
APIRET os2APIENTRY DosQueryFHState(os2HFILE hFile,
PULONG pMode)
{
APIRET rc;
int idx=(int)hFile;
FileTable.lock(idx);
if(FileTable[idx]) {
rc = 0;
*pMode = FileTable[idx]->mode;
} else
rc = 6; //invalid handle
FileTable.unlock(idx);
return rc;
}
示例12: DosResetBuffer
APIRET os2APIENTRY DosResetBuffer(os2HFILE hFile) {
int idx=(int)hFile;
FileTable.lock(idx);
if(FileTable[idx]) {
HANDLE hf=FileTable[idx]->ntFileHandle;
FileTable.unlock(idx);
if(FlushFileBuffers(hf))
return 0;
else
return (APIRET)GetLastError();
} else {
FileTable.unlock(idx);
return 6; //invalid handle
}
}
示例13: DosClose
APIRET os2APIENTRY DosClose(os2HFILE hFile) {
int idx=(int)hFile;
FileTable.lock(idx);
APIRET rc;
if(FileTable[idx]) {
CloseHandle(FileTable[idx]->ntFileHandle);
delete FileTable[idx];
FileTable[idx] = 0;
rc = 0;
} else {
rc = 6; //invalid handle
}
FileTable.unlock(idx);
return rc;
}
示例14: DosQueryFileInfo
APIRET os2APIENTRY DosQueryFileInfo(os2HFILE hFile,
ULONG ulInfoLevel,
PVOID pInfo,
ULONG cbInfoBuf)
{
if(ulInfoLevel!=FIL_STANDARD &&
ulInfoLevel!=FIL_QUERYEASIZE &&
ulInfoLevel!=FIL_QUERYEASFROMLIST)
return 124; //invalid level
APIRET rc;
int idx=(int)hFile;
FileTable.lock(idx);
if(!FileTable[idx]) {
rc = 6; //invalid handle
goto done;
}
if(ulInfoLevel==FIL_QUERYEASFROMLIST) {
rc = 254; //invalid EA name
goto done;
}
BY_HANDLE_FILE_INFORMATION bhfi;
if(!GetFileInformationByHandle(FileTable[idx]->ntFileHandle,&bhfi)) {
rc = (APIRET)GetLastError();
goto done;
}
FILESTATUS4 *fs4;
fs4=(FILESTATUS4 *)pInfo;
if(cbInfoBuf>offsetof(FILESTATUS4,ftimeCreation))
ntfiletime2os2(bhfi.ftCreationTime, &fs4->fdateCreation, &fs4->ftimeCreation);
if(cbInfoBuf>offsetof(FILESTATUS4,ftimeLastAccess))
ntfiletime2os2(bhfi.ftLastAccessTime, &fs4->fdateLastAccess, &fs4->ftimeLastAccess);
if(cbInfoBuf>offsetof(FILESTATUS4,ftimeLastWrite))
ntfiletime2os2(bhfi.ftLastWriteTime, &fs4->fdateLastWrite, &fs4->ftimeLastWrite);
if(cbInfoBuf>offsetof(FILESTATUS4,cbFile))
fs4->cbFile = (ULONG)bhfi.nFileSizeLow;
if(cbInfoBuf>offsetof(FILESTATUS4,cbFileAlloc))
fs4->cbFileAlloc = (ULONG)bhfi.nFileSizeLow;
if(cbInfoBuf>offsetof(FILESTATUS4,attrFile))
ntfileattr2os2(bhfi.dwFileAttributes, &fs4->attrFile);
if(ulInfoLevel==FIL_QUERYEASIZE)
fs4->cbList = 0;
done:
FileTable.unlock(idx);
return rc;
}
示例15: if
APIRET os2APIENTRY DosDupHandle(os2HFILE hFile,
PHFILE pHfile)
{
int srcIdx = (int)hFile;
FileTable.lock(srcIdx);
if(!FileTable[srcIdx]) {
FileTable.unlock(srcIdx);
return 1; //FixMe
}
int dstIdx;
if(*pHfile==(os2HFILE)-1) {
dstIdx = FileTable.findAndLockFree();
if(dstIdx==-1) {
FileTable.unlock(srcIdx);
return 4; //too many open files
}
} else {
dstIdx = (int)*pHfile;
FileTable.lock(dstIdx);
}
if(srcIdx==dstIdx) {
//no-op
FileTable.unlock(srcIdx);
return 0;
}
if(FileTable[dstIdx]) {
CloseHandle(FileTable[dstIdx]->ntFileHandle);
delete FileTable[dstIdx];
FileTable[dstIdx] = 0;
}
APIRET rc;
HANDLE target;
if(DuplicateHandle(GetCurrentProcess(),
FileTable[srcIdx]->ntFileHandle,
GetCurrentProcess(),
&target,
0,
TRUE,
DUPLICATE_SAME_ACCESS
))
{
rc = 0;
FileTable[dstIdx] = new ntFILE;
FileTable[dstIdx]->ntFileHandle = target;
FileTable[dstIdx]->mode = FileTable[srcIdx]->mode;
if(dstIdx==0)
SetStdHandle(STD_INPUT_HANDLE,target);
else if(dstIdx==1)
SetStdHandle(STD_OUTPUT_HANDLE,target);
else if(dstIdx==2)
SetStdHandle(STD_ERROR_HANDLE,target);
} else
rc = 6; //invalid handle
FileTable.unlock(srcIdx);
FileTable.unlock(dstIdx);
return rc;
}