Esempio n. 1
0
Bitu XMS_FreeMemory(Bitu handle) {
	if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
	MEM_ReleasePages(xms_handles[handle].mem);
	xms_handles[handle].mem=-1;
	xms_handles[handle].size=0;
	xms_handles[handle].free=true;
	return 0;
}
Esempio n. 2
0
Bitu XMS_UnlockMemory(Bitu handle) {
 	if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
	if (xms_handles[handle].locked) {
		xms_handles[handle].locked--;
		return 0;
	}
	return XMS_BLOCK_NOT_LOCKED;
}
Esempio n. 3
0
Bitu XMS_MoveMemory(PhysPt bpt) {
	/* Read the block with mem_read's */
	Bitu length=mem_readd(bpt+offsetof(XMS_MemMove,length));
	Bitu src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle));
	union {
		RealPt realpt;
		Bit32u offset;
	} src,dest;
	src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset));
	Bitu dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle));
	dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset));
	PhysPt srcpt,destpt;
	if (src_handle) {
		if (InvalidHandle(src_handle)) {
			return XMS_INVALID_SOURCE_HANDLE;
		}
		if (src.offset>=(xms_handles[src_handle].size*1024U)) {
			return XMS_INVALID_SOURCE_OFFSET;
		}
		if (length>xms_handles[src_handle].size*1024U-src.offset) {
			return XMS_INVALID_LENGTH;
		}
		srcpt=(xms_handles[src_handle].mem*4096)+src.offset;
	} else {
		srcpt=Real2Phys(src.realpt);
	}
	if (dest_handle) {
		if (InvalidHandle(dest_handle)) {
			return XMS_INVALID_DEST_HANDLE;
		}
		if (dest.offset>=(xms_handles[dest_handle].size*1024U)) {
			return XMS_INVALID_DEST_OFFSET;
		}
		if (length>xms_handles[dest_handle].size*1024U-dest.offset) {
			return XMS_INVALID_LENGTH;
		}
		destpt=(xms_handles[dest_handle].mem*4096)+dest.offset;
	} else {
		destpt=Real2Phys(dest.realpt);
	}
//	LOG_MSG("XMS move src %X dest %X length %X",srcpt,destpt,length);
	mem_memcpy(destpt,srcpt,length);
	return 0;
}
Esempio n. 4
0
Bitu XMS_ResizeMemory(Bitu handle, Bitu newSize) {
	if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;	
	// Block has to be unlocked
	if (xms_handles[handle].locked>0) return XMS_BLOCK_LOCKED;
	Bitu pages=newSize/4 + ((newSize & 3) ? 1 : 0);
	if (MEM_ReAllocatePages(xms_handles[handle].mem,pages,true)) {
		xms_handles[handle].size = newSize;
		return 0;
	} else return XMS_OUT_OF_SPACE;
}
Esempio n. 5
0
ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
    Archive* archive = GetArchive(archive_handle);
    if (archive == nullptr)
        return InvalidHandle(ErrorModule::FS);

    if (archive->backend->CreateDirectory(path))
        return RESULT_SUCCESS;
    return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
                      ErrorSummary::Canceled, ErrorLevel::Status);
}
Esempio n. 6
0
Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit16u& size) {
	if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
	lockCount = xms_handles[handle].locked;
	/* Find available blocks */
	numFree=0;
	for (Bitu i=1;i<XMS_HANDLES;i++) {
		if (xms_handles[i].free) numFree++;
	}
	size=(Bit16u)(xms_handles[handle].size);
	return 0;
}
Esempio n. 7
0
ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
    SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
    if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);

    if (0 != shared_memory->base_address)
        return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));

    LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", handle);
    // TODO(yuriks): Verify error code.
    return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
            ErrorSummary::InvalidState, ErrorLevel::Permanent);
}
Esempio n. 8
0
/**
 * Open a Directory from an Archive
 * @param archive_handle Handle to an open Archive object
 * @param path Path to the Directory inside of the Archive
 * @return Opened Directory object
 */
ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
    Archive* archive = GetArchive(archive_handle);
    if (archive == nullptr)
        return InvalidHandle(ErrorModule::FS);

    std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path);
    if (backend == nullptr) {
        return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
                          ErrorSummary::NotFound, ErrorLevel::Permanent);
    }

    auto directory = Common::make_unique<Directory>(std::move(backend), path);
    // TOOD(yuriks): Fix error reporting
    Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
    return MakeResult<Handle>(handle);
}
Esempio n. 9
0
/// Synchronize to an OS service
static Result SendSyncRequest(Handle handle) {
    // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object,
    // so we are forced to use GetFast and manually verify the handle.
    if (!Kernel::g_object_pool.IsValid(handle)) {
        return InvalidHandle(ErrorModule::Kernel).raw;
    }
    Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);

    _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
    DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str());

    ResultVal<bool> wait = object->SyncRequest();
    if (wait.Succeeded() && *wait) {
        Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
    }

    return wait.Code().raw;
}
Esempio n. 10
0
/**
 * Maps a shared memory block to an address in system memory
 * @param handle Shared memory block handle
 * @param address Address in system memory to map shared memory block to
 * @param permissions Memory block map permissions (specified by SVC field)
 * @param other_permissions Memory block map other permissions (specified by SVC field)
 * @return Result of operation, 0 on success, otherwise error code
 */
ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
    MemoryPermission other_permissions) {

    if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
        LOG_ERROR(Kernel_SVC, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
            handle, address);
        return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
                ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
    }
    SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
    if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);

    shared_memory->base_address = address;
    shared_memory->permissions = permissions;
    shared_memory->other_permissions = other_permissions;

    return RESULT_SUCCESS;
}
Esempio n. 11
0
ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
                                          ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) {
    Archive* src_archive = GetArchive(src_archive_handle);
    Archive* dest_archive = GetArchive(dest_archive_handle);
    if (src_archive == nullptr || dest_archive == nullptr)
        return InvalidHandle(ErrorModule::FS);

    if (src_archive == dest_archive) {
        if (src_archive->backend->RenameDirectory(src_path, dest_path))
            return RESULT_SUCCESS;
    } else {
        // TODO: Implement renaming across archives
        return UnimplementedFunction(ErrorModule::FS);
    }

    // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
    // exist or similar. Verify.
    return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
                      ErrorSummary::NothingHappened, ErrorLevel::Status);
}
Esempio n. 12
0
ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
    Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get();
    if (semaphore == nullptr)
        return InvalidHandle(ErrorModule::Kernel);

    if (semaphore->max_count - semaphore->available_count < release_count)
        return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 
                          ErrorSummary::InvalidArgument, ErrorLevel::Permanent);

    *count = semaphore->available_count;
    semaphore->available_count += release_count;

    // Notify some of the threads that the semaphore has been released
    // stop once the semaphore is full again or there are no more waiting threads
    while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) {
        semaphore->Acquire();
    }

    return RESULT_SUCCESS;
}
Esempio n. 13
0
 void Database::import ( const char * folder, const char * file )
 {
     const ::UINT result = ::MsiDatabaseImport(handle(),folder,file);
     if ( result != ERROR_SUCCESS )
     {
         if ( result == ERROR_BAD_PATHNAME ) {
             throw (BadPathName());
         }
         else if ( result == ERROR_FUNCTION_FAILED ) {
             throw (FunctionFailed());
         }
         else if ( result == ERROR_INVALID_HANDLE ) {
             throw (InvalidHandle());
         }
         else if ( result == ERROR_INVALID_PARAMETER ) {
             throw (InvalidParameter());
         }
         UNCHECKED_INSTALLER_ERROR(MsiDatabaseImport,result);
     }
 }
Esempio n. 14
0
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
    s64 nano_seconds) {
    // TODO(bunnei): Do something with nano_seconds, currently ignoring this
    bool unlock_all = true;
    bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated

    DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld",
        handle_count, (wait_all ? "true" : "false"), nano_seconds);

    // Iterate through each handle, synchronize kernel object
    for (s32 i = 0; i < handle_count; i++) {
        if (!Kernel::g_object_pool.IsValid(handles[i])) {
            return InvalidHandle(ErrorModule::Kernel).raw;
        }
        Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);

        DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
            object->GetName().c_str());

        // TODO(yuriks): Verify how the real function behaves when an error happens here
        ResultVal<bool> wait_result = object->WaitSynchronization();
        bool wait = wait_result.Succeeded() && *wait_result;

        if (!wait && !wait_all) {
            *out = i;
            return RESULT_SUCCESS.raw;
        } else {
            unlock_all = false;
        }
    }

    if (wait_all && unlock_all) {
        *out = handle_count;
        return RESULT_SUCCESS.raw;
    }

    // Check for next thread to schedule
    HLE::Reschedule(__func__);

    return RESULT_SUCCESS.raw;
}
Esempio n. 15
0
 void Database::export_ (
     const char * table, const char * folder, const char * file
     )
 {
     const ::UINT result = ::MsiDatabaseExport(
         handle(), table, folder, file
         );
     if ( result != ERROR_SUCCESS )
     {
         if ( result == ERROR_BAD_PATHNAME ) {
             throw (BadPathName());
         }
         else if ( result == ERROR_INVALID_HANDLE ) {
             throw (InvalidHandle());
         }
         else if ( result == ERROR_INVALID_PARAMETER ) {
             throw (InvalidParameter());
         }
         UNCHECKED_INSTALLER_ERROR(MsiDatabaseExport,result);
     }
 }
Esempio n. 16
0
ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
    Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle);
    if (semaphore == nullptr)
        return InvalidHandle(ErrorModule::Kernel);

    if (semaphore->max_count - semaphore->available_count < release_count)
        return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 
                          ErrorSummary::InvalidArgument, ErrorLevel::Permanent);

    *count = semaphore->available_count;
    semaphore->available_count += release_count;

    // Notify some of the threads that the semaphore has been released
    // stop once the semaphore is full again or there are no more waiting threads
    while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
        Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front());
        semaphore->waiting_threads.pop();
        --semaphore->available_count;
    }

    return RESULT_SUCCESS;
}
Esempio n. 17
0
 void Database::merge ( const Database& other, const char * table )
 {
     const ::UINT result = ::MsiDatabaseMerge(
         handle(), other.handle(), table
         );
     if ( result != ERROR_SUCCESS )
     {
         if ( result == ERROR_FUNCTION_FAILED ) {
             throw (FunctionFailed());
         }
         else if ( result == ERROR_INVALID_HANDLE ) {
             throw (InvalidHandle());
         }
         else if ( result == ERROR_INVALID_TABLE ) {
             throw (InvalidTable());
         }
         else if ( result == ERROR_DATATYPE_MISMATCH ) {
             throw (DatatypeMismatch());
         }
         UNCHECKED_INSTALLER_ERROR(MsiDatabaseMerge,result);
     }
 }
Esempio n. 18
0
/// Wait for a handle to synchronize, timeout after the specified nanoseconds
static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
    // TODO(bunnei): Do something with nano_seconds, currently ignoring this
    bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated

    if (!Kernel::g_object_pool.IsValid(handle)) {
        return InvalidHandle(ErrorModule::Kernel).raw;
    }
    Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
    _dbg_assert_(KERNEL, object != nullptr);

    DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
            object->GetName().c_str(), nano_seconds);

    ResultVal<bool> wait = object->WaitSynchronization();

    // Check for next thread to schedule
    if (wait.Succeeded() && *wait) {
        HLE::Reschedule(__func__);
    }

    return wait.Code().raw;
}
Esempio n. 19
0
	HandleType  Mesh::PrevHandle(HandleType h) const 
	{
		integer num = GetHandleElementNum(h), id = GetHandleID(h);
		--id;
		if( num == 5 ) 
		{
			if( id < 0 )
				num = 4;
			else return ComposeHandleNum(ElementNum(MESH),0);
		}
		while( num >= 0 )
		{
			while(id >= 0 && (links[num][id] == -1)) --id;
			if( id == -1 ) 
			{
				--num;
				if( num > 0 ) id = static_cast<integer>(links[num].size())-1;
			}
			else break;
		}
		if( num < 0 ) return InvalidHandle();
		return ComposeHandleNum(num,id);
	}
Esempio n. 20
0
ResultCode CloseArchive(ArchiveHandle handle) {
    if (handle_map.erase(handle) == 0)
        return InvalidHandle(ErrorModule::FS);
    else
        return RESULT_SUCCESS;
}
Esempio n. 21
0
/// Arbitrate an address
ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
    AddressArbiter* object = Kernel::g_handle_table.Get<AddressArbiter>(handle).get();

    if (object == nullptr)
        return InvalidHandle(ErrorModule::Kernel);

    switch (type) {

    // Signal thread(s) waiting for arbitrate address...
    case ArbitrationType::Signal:
        // Negative value means resume all threads
        if (value < 0) {
            ArbitrateAllThreads(address);
        } else {
            // Resume first N threads
            for(int i = 0; i < value; i++)
                ArbitrateHighestPriorityThread(address);
        }
        break;

    // Wait current thread (acquire the arbiter)...
    case ArbitrationType::WaitIfLessThan:
        if ((s32)Memory::Read32(address) <= value) {
            Kernel::WaitCurrentThread_ArbitrateAddress(address);
            HLE::Reschedule(__func__);
        }
        break;
    case ArbitrationType::WaitIfLessThanWithTimeout:
        if ((s32)Memory::Read32(address) <= value) {
            Kernel::WaitCurrentThread_ArbitrateAddress(address);
            Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds);
            HLE::Reschedule(__func__);
        }
        break;
    case ArbitrationType::DecrementAndWaitIfLessThan:
    {
        s32 memory_value = Memory::Read32(address) - 1;
        Memory::Write32(address, memory_value);
        if (memory_value <= value) {
            Kernel::WaitCurrentThread_ArbitrateAddress(address);
            HLE::Reschedule(__func__);
        }
        break;
    }
    case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout:
    {
        s32 memory_value = Memory::Read32(address) - 1;
        Memory::Write32(address, memory_value);
        if (memory_value <= value) {
            Kernel::WaitCurrentThread_ArbitrateAddress(address);
            Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds);
            HLE::Reschedule(__func__);
        }
        break;
    }

    default:
        LOG_ERROR(Kernel, "unknown type=%d", type);
        return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage);
    }
    return RESULT_SUCCESS;
}
Esempio n. 22
0
	bool Storage::isValid() const 
	{
		return handle != InvalidHandle() && GetMeshLink()->isValidElement(handle);
	}
Esempio n. 23
0
Bitu XMS_LockMemory(Bitu handle, Bit32u& address) {
	if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
	if (xms_handles[handle].locked<255) xms_handles[handle].locked++;
	address = xms_handles[handle].mem*4096;
	return 0;
}