mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
183 lines
4.3 KiB
C++
183 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
#include "handles.h"
|
|
#include "mimalloc.h"
|
|
|
|
#include <pthread.h>
|
|
|
|
namespace kernel32 {
|
|
|
|
struct FsObject : ObjectBase {
|
|
std::mutex m;
|
|
int fd = -1;
|
|
std::filesystem::path canonicalPath;
|
|
uint32_t shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
bool deletePending = false;
|
|
bool closeOnDestroy = true;
|
|
|
|
~FsObject() override;
|
|
[[nodiscard]] bool valid() const { return fd >= 0; }
|
|
|
|
protected:
|
|
explicit FsObject(ObjectType type, int fd) : ObjectBase(type), fd(fd) {}
|
|
};
|
|
|
|
struct FileObject final : FsObject {
|
|
static constexpr ObjectType kType = ObjectType::File;
|
|
|
|
off64_t filePos = 0;
|
|
bool overlapped = false;
|
|
bool appendOnly = false;
|
|
bool isPipe = false;
|
|
|
|
explicit FileObject(int fd) : FsObject(kType, fd) {
|
|
if (fd >= 0) {
|
|
off64_t pos = lseek64(fd, 0, SEEK_CUR);
|
|
if (pos == -1 && errno == ESPIPE) {
|
|
isPipe = true;
|
|
} else if (pos >= 0) {
|
|
filePos = pos;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct DirectoryObject final : FsObject {
|
|
static constexpr ObjectType kType = ObjectType::Directory;
|
|
|
|
uint64_t enumCookie = 0;
|
|
|
|
explicit DirectoryObject(int dirfd) : FsObject(kType, dirfd) {}
|
|
};
|
|
|
|
struct ProcessObject final : WaitableObject {
|
|
static constexpr ObjectType kType = ObjectType::Process;
|
|
|
|
pid_t pid;
|
|
int pidfd;
|
|
DWORD exitCode = STILL_ACTIVE;
|
|
bool forcedExitCode = false;
|
|
|
|
explicit ProcessObject(pid_t pid, int pidfd) : WaitableObject(kType), pid(pid), pidfd(pidfd) {}
|
|
|
|
~ProcessObject() override {
|
|
std::lock_guard lk(m);
|
|
if (pidfd != -1) {
|
|
close(pidfd);
|
|
pidfd = -1;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct ThreadObject final : WaitableObject {
|
|
static constexpr ObjectType kType = ObjectType::Thread;
|
|
|
|
pthread_t thread;
|
|
DWORD exitCode = STILL_ACTIVE;
|
|
unsigned int suspendCount = 0;
|
|
TIB *tib = nullptr;
|
|
|
|
explicit ThreadObject(pthread_t thread) : WaitableObject(kType), thread(thread) {}
|
|
|
|
~ThreadObject() override {
|
|
std::lock_guard lk(m);
|
|
// Threads are detached at creation; we can safely drop
|
|
if (tib) {
|
|
wibo::destroyTib(tib);
|
|
tib = nullptr;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct MutexObject final : WaitableObject {
|
|
static constexpr ObjectType kType = ObjectType::Mutex;
|
|
|
|
bool ownerValid = false;
|
|
pthread_t owner{};
|
|
unsigned int recursionCount = 0;
|
|
bool abandoned = false; // Owner exited without releasing
|
|
|
|
MutexObject() : WaitableObject(kType) { signaled.store(true, std::memory_order_relaxed); }
|
|
|
|
void noteOwnerExit(/*pthread_t tid or emu tid*/) {
|
|
std::lock_guard lk(m);
|
|
if (ownerValid /* && matches tid if you store emu id */) {
|
|
ownerValid = false;
|
|
recursionCount = 0;
|
|
abandoned = true;
|
|
signaled.store(true, std::memory_order_release);
|
|
cv.notify_one();
|
|
}
|
|
}
|
|
};
|
|
|
|
struct EventObject final : WaitableObject {
|
|
static constexpr ObjectType kType = ObjectType::Event;
|
|
|
|
bool manualReset = false;
|
|
|
|
explicit EventObject(bool manual) : WaitableObject(kType), manualReset(manual) {}
|
|
|
|
void set() {
|
|
bool resetAll = false;
|
|
{
|
|
std::lock_guard lk(m);
|
|
signaled.store(true, std::memory_order_release);
|
|
resetAll = manualReset;
|
|
}
|
|
if (resetAll) {
|
|
cv.notify_all();
|
|
} else {
|
|
cv.notify_one();
|
|
}
|
|
}
|
|
|
|
void reset() {
|
|
std::lock_guard lk(m);
|
|
signaled.store(false, std::memory_order_release);
|
|
}
|
|
};
|
|
|
|
struct SemaphoreObject final : WaitableObject {
|
|
static constexpr ObjectType kType = ObjectType::Semaphore;
|
|
|
|
LONG count = 0;
|
|
LONG maxCount = 0;
|
|
|
|
SemaphoreObject(LONG initial, LONG maximum) : WaitableObject(kType), count(initial), maxCount(maximum) {}
|
|
};
|
|
|
|
struct HeapObject : public ObjectBase {
|
|
static constexpr ObjectType kType = ObjectType::Heap;
|
|
|
|
std::mutex m;
|
|
mi_heap_t *heap;
|
|
DWORD createFlags = 0;
|
|
SIZE_T initialSize = 0;
|
|
SIZE_T maximumSize = 0;
|
|
DWORD compatibility = 0;
|
|
bool isProcessHeap = false;
|
|
|
|
explicit HeapObject(mi_heap_t *heap) : ObjectBase(kType), heap(heap) {}
|
|
~HeapObject() override;
|
|
};
|
|
|
|
inline constexpr uintptr_t kPseudoCurrentProcessHandleValue = static_cast<uintptr_t>(-1);
|
|
inline constexpr uintptr_t kPseudoCurrentThreadHandleValue = static_cast<uintptr_t>(-2);
|
|
|
|
inline bool isPseudoCurrentProcessHandle(HANDLE h) {
|
|
uintptr_t rawHandle = reinterpret_cast<uintptr_t>(h);
|
|
return rawHandle == kPseudoCurrentProcessHandleValue;
|
|
}
|
|
|
|
inline bool isPseudoCurrentThreadHandle(HANDLE h) {
|
|
uintptr_t rawHandle = reinterpret_cast<uintptr_t>(h);
|
|
return rawHandle == kPseudoCurrentThreadHandleValue;
|
|
}
|
|
|
|
void tryMarkExecutable(void *mem);
|
|
void setLastErrorFromErrno();
|
|
|
|
} // namespace kernel32
|