Esempio n. 1
0
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;
}
Esempio n. 2
0
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
        }        
}
Esempio n. 3
0
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
        }
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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();
        }
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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
        }
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
APIRET os2APIENTRY DosSetFileLocks(os2HFILE hFile,
                                   PFILELOCK pflUnlock,
                                   PFILELOCK pflLock,
                                   ULONG /*timeout*/,
                                   ULONG flags)
{
        APIRET rc;
        int idx=(int)hFile;
        FileTable.lock(idx);
        if(FileTable[idx]) {
                rc=0;
                if(pflLock) {
                        OVERLAPPED o;
                        memset(&o,0,sizeof(o));
                        o.Offset = pflLock->lOffset;
                        o.OffsetHigh = 0;
                        if(!LockFileEx(FileTable[idx]->ntFileHandle,
                                       flags&1?0:LOCKFILE_EXCLUSIVE_LOCK,
                                       0,
                                       pflLock->lRange, 0,
                                       0
                                    )) {
                                rc = (APIRET)GetLastError();
                        }
                }
                if(rc==0 && pflUnlock) {
                        if(!UnlockFile(FileTable[idx]->ntFileHandle,
                                       pflUnlock->lOffset, 0,
                                       pflUnlock->lRange, 0
                                    )) {
                                UnlockFile(FileTable[idx]->ntFileHandle,
                                           pflLock->lOffset,0,
                                           pflLock->lRange,0
                                          );
                                rc = (APIRET)GetLastError();
                        }
                }
        } else
                rc = 6; //invalid handle
        FileTable.unlock(idx);
        return rc;
}
Esempio n. 12
0
APIRET os2APIENTRY DosSetFileSize(os2HFILE hFile,
                                  ULONG cbSize)
{
        APIRET rc;
        int idx=(int)hFile;
        FileTable.lock(idx);
        if(FileTable[idx]) {
                APIRET rc;
                HANDLE hf=FileTable[idx]->ntFileHandle;
                DWORD current = SetFilePointer(hf,0,0,1);
                SetFilePointer(hf,(DWORD)cbSize,0,0);
                if(SetEndOfFile(hf))
                        rc = 0;
                else
                        rc = (APIRET)GetLastError();
                SetFilePointer(hf,current,0,0);
        } else {
                rc = 6; //invalid handle
        }
        FileTable.unlock(idx);
        return rc;
}
Esempio n. 13
0
APIRET os2APIENTRY DosWrite(os2HFILE hFile,
                            PVOID pBuffer,
                            ULONG cbWrite,
                            PULONG pcbActual)
{
        int idx=(int)hFile;
        FileTable.lock(idx);
        if(FileTable[idx]) {
                HANDLE hf=FileTable[idx]->ntFileHandle;
                FileTable.unlock(idx);
                if(WriteFile(hf,
                            (LPVOID)pBuffer,
                            (DWORD)cbWrite,
                            (LPDWORD)pcbActual,
                            0
                           ))
                        return 0;
                else
                        return (APIRET)GetLastError();
        } else {
                FileTable.unlock(idx);
                return 6; //invalid handle
        }        
}
Esempio n. 14
0
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();
    } else if (handle == CurrentProcess) {
        LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
        return nullptr;
    }

    if (!IsValid(handle)) {
        return nullptr;
    }
    return objects[GetSlot(handle)];
}

void HandleTable::Clear() {
    for (u16 i = 0; i < MAX_COUNT; ++i) {
        generations[i] = i + 1;
        objects[i] = nullptr;
    }
    next_free_slot = 0;
}

/// Initialize the kernel
void Init() {
    Kernel::ThreadingInit();
    Kernel::TimersInit();

    Object::next_object_id = 0;
}

/// Shutdown the kernel
void Shutdown() {
    Kernel::ThreadingShutdown();
    Kernel::TimersShutdown();
    g_handle_table.Clear(); // Free all kernel objects
    g_current_process = nullptr;
}

} // namespace
Esempio n. 15
0
/// Shutdown the kernel
void Shutdown() {
    Kernel::ThreadingShutdown();
    Kernel::TimersShutdown();
    g_handle_table.Clear(); // Free all kernel objects
    g_current_process = nullptr;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
/// Shutdown the kernel
void Shutdown() {
    Kernel::ThreadingShutdown();
    Kernel::TimersShutdown();
    g_handle_table.Clear(); // Free all kernel objects
}
Esempio n. 18
0
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;
}

SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
    if (handle == CurrentThread) {
        return GetCurrentThread();
    } else if (handle == CurrentProcess) {
        LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
        return nullptr;
    }

    if (!IsValid(handle)) {
        return nullptr;
    }
    return objects[GetSlot(handle)];
}

void HandleTable::Clear() {
    for (size_t i = 0; i < MAX_COUNT; ++i) {
        generations[i] = i + 1;
        objects[i] = nullptr;
    }
    next_free_slot = 0;
}

/// Initialize the kernel
void Init() {
    Kernel::ThreadingInit();
    Kernel::TimersInit();
}

/// Shutdown the kernel
void Shutdown() {
    Kernel::ThreadingShutdown();
    Kernel::TimersShutdown();
    g_handle_table.Clear(); // Free all kernel objects
}

/**
 * Loads executable stored at specified address
 * @entry_point Entry point in memory of loaded executable
 * @return True on success, otherwise false
 */
bool LoadExec(u32 entry_point) {
    Core::g_app_core->SetPC(entry_point);

    // 0x30 is the typical main thread priority I've seen used so far
    g_main_thread = Kernel::SetupMainThread(0x30, Kernel::DEFAULT_STACK_SIZE);
    // Setup the idle thread
    Kernel::SetupIdleThread();

    return true;
}

} // namespace
Esempio n. 19
0
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;
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
APIRET os2APIENTRY DosOpen(PCSZ   pszFileName,
                           PHFILE pHf,
                           PULONG pulAction,
                           ULONG  cbFile,
                           ULONG  ulAttribute,
                           ULONG  fsOpenFlags,
                           ULONG  fsOpenMode,
                           PEAOP2 peaop2)
{
        int idx=FileTable.findAndLockFree();
        if(idx==-1) return 4; //too many open files
        ntFILE *ntFile=new ntFILE;
        if(!ntFile) return 8; //not enough memory
        if(peaop2) return 282; //eas not supported
        char szName[MAX_PATH];
        DWORD fdwAccess;
        DWORD fdwShareMode;
        LPSECURITY_ATTRIBUTES lpsa;
        DWORD fdwCreate;
        DWORD fdwAttrsAndFlags;
        HANDLE hTemplateFile;

        //szName, FixMe: named pipe namespace
        strcpy(szName,pszFileName);
        //fdwAcess
        if((fsOpenMode&0x7)==OPEN_ACCESS_READONLY)
                fdwAccess = GENERIC_READ;
        else if((fsOpenMode&0x7)==OPEN_ACCESS_WRITEONLY)
                fdwAccess = GENERIC_WRITE;
        else if((fsOpenMode&0x7)==OPEN_ACCESS_READWRITE)
                fdwAccess = GENERIC_READ|GENERIC_WRITE;
        else
                return 87; //invalid parameter
        //fdwShareMode
        if((fsOpenMode&0x70)==OPEN_SHARE_DENYREADWRITE)
                fdwShareMode = 0;
        else if((fsOpenMode&0x70)==OPEN_SHARE_DENYWRITE)
                fdwShareMode = FILE_SHARE_READ;
        else if((fsOpenMode&0x70)==OPEN_SHARE_DENYREAD)
                fdwShareMode = FILE_SHARE_WRITE;
        else if((fsOpenMode&0x70)==OPEN_SHARE_DENYNONE)
                fdwShareMode = FILE_SHARE_READ+FILE_SHARE_WRITE;
        else 
                return 87; //invalid parameter
        //lpsa
        SECURITY_ATTRIBUTES sa;
        if((fsOpenMode&OPEN_FLAGS_NOINHERIT))
                lpsa = 0;
        else {
                memset(&sa,0,sizeof(sa));
                sa.nLength = sizeof(sa);
                sa.bInheritHandle = TRUE;
                lpsa = &sa;
        }
        //fdwCreate
        switch(fsOpenFlags&0xff) {
                case OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_FAIL_IF_EXISTS:
                        return 1; //FixMe
                case OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS:
                        fdwCreate = OPEN_EXISTING;
                        break;
                case OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_REPLACE_IF_EXISTS:
                        fdwCreate = TRUNCATE_EXISTING;
                        break;
                case OPEN_ACTION_CREATE_IF_NEW|OPEN_ACTION_FAIL_IF_EXISTS:
                        fdwCreate = CREATE_NEW;
                        break;
                case OPEN_ACTION_CREATE_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS:
                        fdwCreate = OPEN_ALWAYS;
                        break;
                case OPEN_ACTION_CREATE_IF_NEW|OPEN_ACTION_REPLACE_IF_EXISTS:
                        fdwCreate = CREATE_ALWAYS;
                        break;
                default:
                        return 87; //invalid parameter, FixMe: is this legal under os/2?
        }
        //fdwAttrsAndFlags
        fdwAttrsAndFlags = 0;
        if(ulAttribute&FILE_ARCHIVED)
                fdwAttrsAndFlags |= FILE_ATTRIBUTE_ARCHIVE;
        if(ulAttribute&FILE_SYSTEM)
                fdwAttrsAndFlags |= FILE_ATTRIBUTE_SYSTEM;
        if(ulAttribute&FILE_HIDDEN)
                fdwAttrsAndFlags |= FILE_ATTRIBUTE_HIDDEN;
        if(ulAttribute&FILE_READONLY)
                fdwAttrsAndFlags |= FILE_ATTRIBUTE_READONLY;
        if(fsOpenMode&OPEN_FLAGS_WRITE_THROUGH)
                fdwAttrsAndFlags |= FILE_FLAG_WRITE_THROUGH;
        if(fsOpenMode&OPEN_FLAGS_NO_CACHE)
                fdwAttrsAndFlags |= FILE_FLAG_WRITE_THROUGH;
        if((fsOpenMode&0x700)==OPEN_FLAGS_SEQUENTIAL)
                fdwAttrsAndFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
        if((fsOpenMode&0x700)==OPEN_FLAGS_RANDOM)
                fdwAttrsAndFlags |= FILE_FLAG_RANDOM_ACCESS;
        //hTemplateFile
        hTemplateFile = 0;

        HANDLE hf = CreateFile(szName, fdwAccess, fdwShareMode, lpsa, fdwCreate, fdwAttrsAndFlags, hTemplateFile);
        if(hf==INVALID_HANDLE_VALUE)
                return (APIRET)GetLastError();

        //->pulAction
        if(fdwCreate==CREATE_ALWAYS || fdwCreate==OPEN_ALWAYS) {
                if(GetLastError()==183/*ERROR_ALREADY_EXIST*/)
                        *pulAction = fdwCreate==CREATE_ALWAYS?FILE_CREATED:FILE_EXISTED;
                else
                        *pulAction = FILE_CREATED;
        } else {
                *pulAction = FILE_EXISTED;
        }
        if((fsOpenFlags&0x0f)==OPEN_ACTION_REPLACE_IF_EXISTS) {
                //set file size
                SetFilePointer(hf,cbFile,0,0);
                SetEndOfFile(hf); //FixMe
                SetFilePointer(hf,0,0,0);
        }
        *pHf = (os2HFILE)idx;

        ntFile->ntFileHandle = hf;
        ntFile->mode = fsOpenMode;
        FileTable[idx] = ntFile;
        FileTable.unlock(idx);
        
        return 0;
}