mirror of
https://github.com/decompals/wibo.git
synced 2025-10-17 15:45:15 +00:00
Split kernel32 into separate files (part 1)
This commit is contained in:
parent
c099a1b577
commit
9ea5b24b67
@ -36,6 +36,12 @@ add_executable(wibo
|
||||
dll/bcrypt.cpp
|
||||
dll/crt.cpp
|
||||
dll/kernel32.cpp
|
||||
dll/kernel32/errhandlingapi.cpp
|
||||
dll/kernel32/fibersapi.cpp
|
||||
dll/kernel32/processthreadsapi.cpp
|
||||
dll/kernel32/sysinfoapi.cpp
|
||||
dll/kernel32/synchapi.cpp
|
||||
dll/kernel32/wow64apiset.cpp
|
||||
dll/lmgr.cpp
|
||||
dll/mscoree.cpp
|
||||
dll/msvcrt.cpp
|
||||
|
2
common.h
2
common.h
@ -48,6 +48,8 @@ typedef ULONG *PULONG;
|
||||
typedef int64_t LARGE_INTEGER;
|
||||
typedef LARGE_INTEGER *PLARGE_INTEGER;
|
||||
typedef uintptr_t ULONG_PTR;
|
||||
typedef ULONG_PTR DWORD_PTR;
|
||||
typedef DWORD_PTR *PDWORD_PTR;
|
||||
typedef char *LPSTR;
|
||||
typedef const char *LPCSTR;
|
||||
typedef uint16_t *LPWSTR;
|
||||
|
1087
dll/kernel32.cpp
1087
dll/kernel32.cpp
File diff suppressed because it is too large
Load Diff
56
dll/kernel32/errhandlingapi.cpp
Normal file
56
dll/kernel32/errhandlingapi.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "common.h"
|
||||
#include "kernel32.h"
|
||||
|
||||
namespace {
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER g_topLevelExceptionFilter = nullptr;
|
||||
UINT g_processErrorMode = 0;
|
||||
} // namespace
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
DWORD WIN_FUNC GetLastError() {
|
||||
DEBUG_LOG("GetLastError() -> %u\n", wibo::lastError);
|
||||
return wibo::lastError;
|
||||
}
|
||||
|
||||
void WIN_FUNC SetLastError(DWORD dwErrCode) {
|
||||
DEBUG_LOG("SetLastError(%u)\n", dwErrCode);
|
||||
wibo::lastError = dwErrCode;
|
||||
}
|
||||
|
||||
void WIN_FUNC RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,
|
||||
const ULONG_PTR *lpArguments) {
|
||||
DEBUG_LOG("RaiseException(0x%x, 0x%x, %u, %p)\n", dwExceptionCode, dwExceptionFlags, nNumberOfArguments,
|
||||
lpArguments);
|
||||
(void)dwExceptionFlags;
|
||||
(void)nNumberOfArguments;
|
||||
(void)lpArguments;
|
||||
exit(static_cast<int>(dwExceptionCode));
|
||||
}
|
||||
|
||||
PVOID WIN_FUNC AddVectoredExceptionHandler(ULONG First, PVECTORED_EXCEPTION_HANDLER Handler) {
|
||||
DEBUG_LOG("STUB: AddVectoredExceptionHandler(%u, %p)\n", First, Handler);
|
||||
return reinterpret_cast<PVOID>(Handler);
|
||||
}
|
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WIN_FUNC
|
||||
SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
|
||||
DEBUG_LOG("STUB: SetUnhandledExceptionFilter(%p)\n", lpTopLevelExceptionFilter);
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER previous = g_topLevelExceptionFilter;
|
||||
g_topLevelExceptionFilter = lpTopLevelExceptionFilter;
|
||||
return previous;
|
||||
}
|
||||
|
||||
LONG WIN_FUNC UnhandledExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
|
||||
DEBUG_LOG("STUB: UnhandledExceptionFilter(%p)\n", ExceptionInfo);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
UINT WIN_FUNC SetErrorMode(UINT uMode) {
|
||||
DEBUG_LOG("STUB: SetErrorMode(%u)\n", uMode);
|
||||
UINT previous = g_processErrorMode;
|
||||
g_processErrorMode = uMode;
|
||||
return previous;
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
63
dll/kernel32/fibersapi.cpp
Normal file
63
dll/kernel32/fibersapi.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "kernel32.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
constexpr size_t MAX_FLS_VALUES = 0x100;
|
||||
static bool flsValuesUsed[MAX_FLS_VALUES] = {false};
|
||||
static void *flsValues[MAX_FLS_VALUES];
|
||||
|
||||
DWORD WIN_FUNC FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) {
|
||||
DEBUG_LOG("FlsAlloc(%p)", lpCallback);
|
||||
// If the function succeeds, the return value is an FLS index initialized to zero.
|
||||
for (size_t i = 0; i < MAX_FLS_VALUES; i++) {
|
||||
if (flsValuesUsed[i] == false) {
|
||||
flsValuesUsed[i] = true;
|
||||
flsValues[i] = nullptr;
|
||||
DEBUG_LOG(" -> %d\n", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
DEBUG_LOG(" -> -1\n");
|
||||
wibo::lastError = 1;
|
||||
return FLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FlsFree(DWORD dwFlsIndex) {
|
||||
DEBUG_LOG("FlsFree(%u)\n", dwFlsIndex);
|
||||
if (dwFlsIndex >= 0 && dwFlsIndex < MAX_FLS_VALUES && flsValuesUsed[dwFlsIndex]) {
|
||||
flsValuesUsed[dwFlsIndex] = false;
|
||||
return TRUE;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PVOID WIN_FUNC FlsGetValue(DWORD dwFlsIndex) {
|
||||
VERBOSE_LOG("FlsGetValue(%u)\n", dwFlsIndex);
|
||||
PVOID result = nullptr;
|
||||
if (dwFlsIndex >= 0 && dwFlsIndex < MAX_FLS_VALUES && flsValuesUsed[dwFlsIndex]) {
|
||||
result = flsValues[dwFlsIndex];
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsgetvalue
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
}
|
||||
// DEBUG_LOG(" -> %p\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData) {
|
||||
VERBOSE_LOG("FlsSetValue(%u, %p)\n", dwFlsIndex, lpFlsData);
|
||||
if (dwFlsIndex >= 0 && dwFlsIndex < MAX_FLS_VALUES && flsValuesUsed[dwFlsIndex]) {
|
||||
flsValues[dwFlsIndex] = lpFlsData;
|
||||
return TRUE;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
54
dll/kernel32/internal.h
Normal file
54
dll/kernel32/internal.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "kernel32.h"
|
||||
#include <pthread.h>
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
struct ThreadObject {
|
||||
pthread_t thread;
|
||||
bool finished = false;
|
||||
bool joined = false;
|
||||
bool detached = false;
|
||||
bool synthetic = false;
|
||||
DWORD exitCode = 0;
|
||||
int refCount = 1;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
unsigned int suspendCount = 0;
|
||||
};
|
||||
|
||||
struct MutexObject {
|
||||
pthread_mutex_t mutex;
|
||||
bool ownerValid = false;
|
||||
pthread_t owner = 0;
|
||||
unsigned int recursionCount = 0;
|
||||
std::u16string name;
|
||||
int refCount = 1;
|
||||
};
|
||||
|
||||
struct EventObject {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
bool manualReset = false;
|
||||
bool signaled = false;
|
||||
std::u16string name;
|
||||
int refCount = 1;
|
||||
};
|
||||
|
||||
struct SemaphoreObject {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
LONG count = 0;
|
||||
LONG maxCount = 0;
|
||||
std::u16string name;
|
||||
int refCount = 1;
|
||||
};
|
||||
|
||||
void releaseMutexObject(MutexObject *obj);
|
||||
void releaseEventObject(EventObject *obj);
|
||||
void releaseSemaphoreObject(SemaphoreObject *obj);
|
||||
void resetOverlappedEvent(OVERLAPPED *ov);
|
||||
void signalOverlappedEvent(OVERLAPPED *ov);
|
||||
|
||||
} // namespace kernel32
|
193
dll/kernel32/kernel32.h
Normal file
193
dll/kernel32/kernel32.h
Normal file
@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// errhandlingapi.h
|
||||
constexpr DWORD EXCEPTION_MAXIMUM_PARAMETERS = 15;
|
||||
|
||||
struct EXCEPTION_RECORD {
|
||||
DWORD ExceptionCode;
|
||||
DWORD ExceptionFlags;
|
||||
EXCEPTION_RECORD *ExceptionRecord;
|
||||
PVOID ExceptionAddress;
|
||||
DWORD NumberParameters;
|
||||
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
|
||||
};
|
||||
|
||||
using PEXCEPTION_RECORD = EXCEPTION_RECORD *;
|
||||
using PCONTEXT = void *;
|
||||
|
||||
struct EXCEPTION_POINTERS {
|
||||
PEXCEPTION_RECORD ExceptionRecord;
|
||||
PCONTEXT ContextRecord;
|
||||
};
|
||||
|
||||
using PEXCEPTION_POINTERS = EXCEPTION_POINTERS *;
|
||||
using PVECTORED_EXCEPTION_HANDLER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo);
|
||||
using LPTOP_LEVEL_EXCEPTION_FILTER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo);
|
||||
|
||||
constexpr LONG EXCEPTION_CONTINUE_EXECUTION = static_cast<LONG>(-1);
|
||||
constexpr LONG EXCEPTION_CONTINUE_SEARCH = 0;
|
||||
constexpr LONG EXCEPTION_EXECUTE_HANDLER = 1;
|
||||
|
||||
// synchapi.h constants
|
||||
constexpr DWORD WAIT_OBJECT_0 = 0x00000000;
|
||||
constexpr DWORD WAIT_ABANDONED = 0x00000080;
|
||||
constexpr DWORD WAIT_TIMEOUT = 0x00000102;
|
||||
constexpr DWORD WAIT_FAILED = 0xFFFFFFFF;
|
||||
constexpr DWORD INFINITE = 0xFFFFFFFF;
|
||||
|
||||
// minwinbase.h
|
||||
struct SECURITY_ATTRIBUTES {
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
};
|
||||
|
||||
using PSECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES *;
|
||||
using LPSECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES *;
|
||||
|
||||
// sysinfoapi.h
|
||||
struct SYSTEM_INFO {
|
||||
union {
|
||||
DWORD dwOemId;
|
||||
struct {
|
||||
WORD wProcessorArchitecture;
|
||||
WORD wReserved;
|
||||
};
|
||||
};
|
||||
DWORD dwPageSize;
|
||||
LPVOID lpMinimumApplicationAddress;
|
||||
LPVOID lpMaximumApplicationAddress;
|
||||
DWORD_PTR dwActiveProcessorMask;
|
||||
DWORD dwNumberOfProcessors;
|
||||
DWORD dwProcessorType;
|
||||
DWORD dwAllocationGranularity;
|
||||
WORD wProcessorLevel;
|
||||
WORD wProcessorRevision;
|
||||
};
|
||||
|
||||
using LPSYSTEM_INFO = SYSTEM_INFO *;
|
||||
|
||||
// processthreadsapi.h
|
||||
struct PROCESS_INFORMATION {
|
||||
HANDLE hProcess;
|
||||
HANDLE hThread;
|
||||
DWORD dwProcessId;
|
||||
DWORD dwThreadId;
|
||||
};
|
||||
|
||||
using PPROCESS_INFORMATION = PROCESS_INFORMATION *;
|
||||
using LPPROCESS_INFORMATION = PROCESS_INFORMATION *;
|
||||
|
||||
struct STARTUPINFOA {
|
||||
DWORD cb;
|
||||
LPSTR lpReserved;
|
||||
LPSTR lpDesktop;
|
||||
LPSTR lpTitle;
|
||||
DWORD dwX;
|
||||
DWORD dwY;
|
||||
DWORD dwXSize;
|
||||
DWORD dwYSize;
|
||||
DWORD dwXCountChars;
|
||||
DWORD dwYCountChars;
|
||||
DWORD dwFillAttribute;
|
||||
DWORD dwFlags;
|
||||
WORD wShowWindow;
|
||||
WORD cbReserved2;
|
||||
unsigned char *lpReserved2;
|
||||
HANDLE hStdInput;
|
||||
HANDLE hStdOutput;
|
||||
HANDLE hStdError;
|
||||
};
|
||||
|
||||
using LPSTARTUPINFOA = STARTUPINFOA *;
|
||||
|
||||
struct STARTUPINFOW {
|
||||
DWORD cb;
|
||||
LPWSTR lpReserved;
|
||||
LPWSTR lpDesktop;
|
||||
LPWSTR lpTitle;
|
||||
DWORD dwX;
|
||||
DWORD dwY;
|
||||
DWORD dwXSize;
|
||||
DWORD dwYSize;
|
||||
DWORD dwXCountChars;
|
||||
DWORD dwYCountChars;
|
||||
DWORD dwFillAttribute;
|
||||
DWORD dwFlags;
|
||||
WORD wShowWindow;
|
||||
WORD cbReserved2;
|
||||
unsigned char *lpReserved2;
|
||||
HANDLE hStdInput;
|
||||
HANDLE hStdOutput;
|
||||
HANDLE hStdError;
|
||||
};
|
||||
|
||||
using LPSTARTUPINFOW = STARTUPINFOW *;
|
||||
|
||||
// fibersapi.h
|
||||
using PFLS_CALLBACK_FUNCTION = void (*)(void *);
|
||||
constexpr DWORD FLS_OUT_OF_INDEXES = 0xFFFFFFFF;
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
// fibersapi.h
|
||||
DWORD WIN_FUNC FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback);
|
||||
BOOL WIN_FUNC FlsFree(DWORD dwFlsIndex);
|
||||
PVOID WIN_FUNC FlsGetValue(DWORD dwFlsIndex);
|
||||
BOOL WIN_FUNC FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData);
|
||||
|
||||
// errhandlingapi.h
|
||||
DWORD WIN_FUNC GetLastError();
|
||||
void WIN_FUNC SetLastError(DWORD dwErrCode);
|
||||
void WIN_FUNC RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,
|
||||
const ULONG_PTR *lpArguments);
|
||||
PVOID WIN_FUNC AddVectoredExceptionHandler(ULONG First, PVECTORED_EXCEPTION_HANDLER Handler);
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WIN_FUNC
|
||||
SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
LONG WIN_FUNC UnhandledExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo);
|
||||
UINT WIN_FUNC SetErrorMode(UINT uMode);
|
||||
|
||||
// wow64apiset.h
|
||||
BOOL WIN_FUNC Wow64DisableWow64FsRedirection(PVOID *OldValue);
|
||||
BOOL WIN_FUNC Wow64RevertWow64FsRedirection(PVOID OldValue);
|
||||
BOOL WIN_FUNC IsWow64Process(HANDLE hProcess, PBOOL Wow64Process);
|
||||
|
||||
// sysinfoapi.h
|
||||
void WIN_FUNC GetSystemInfo(LPSYSTEM_INFO lpSystemInfo);
|
||||
|
||||
// processthreadsapi.h
|
||||
HANDLE WIN_FUNC GetCurrentProcess();
|
||||
DWORD WIN_FUNC GetCurrentProcessId();
|
||||
DWORD WIN_FUNC GetCurrentThreadId();
|
||||
BOOL WIN_FUNC GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask);
|
||||
BOOL WIN_FUNC SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask);
|
||||
void WIN_FUNC ExitProcess(UINT uExitCode);
|
||||
BOOL WIN_FUNC TerminateProcess(HANDLE hProcess, UINT uExitCode);
|
||||
BOOL WIN_FUNC GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);
|
||||
BOOL WIN_FUNC CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation);
|
||||
BOOL WIN_FUNC CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
// synchapi.h
|
||||
HANDLE WIN_FUNC CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName);
|
||||
HANDLE WIN_FUNC CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName);
|
||||
BOOL WIN_FUNC ReleaseMutex(HANDLE hMutex);
|
||||
HANDLE WIN_FUNC CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName);
|
||||
HANDLE WIN_FUNC CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName);
|
||||
BOOL WIN_FUNC SetEvent(HANDLE hEvent);
|
||||
BOOL WIN_FUNC ResetEvent(HANDLE hEvent);
|
||||
HANDLE WIN_FUNC CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCSTR lpName);
|
||||
HANDLE WIN_FUNC CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCWSTR lpName);
|
||||
BOOL WIN_FUNC ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, PLONG lpPreviousCount);
|
||||
DWORD WIN_FUNC WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
|
||||
|
||||
} // namespace kernel32
|
259
dll/kernel32/processthreadsapi.cpp
Normal file
259
dll/kernel32/processthreadsapi.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "kernel32.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
DWORD_PTR computeSystemAffinityMask() {
|
||||
long reported = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (reported <= 0) {
|
||||
reported = 1;
|
||||
}
|
||||
const auto bitCount = static_cast<unsigned int>(std::numeric_limits<DWORD_PTR>::digits);
|
||||
const auto usable = static_cast<unsigned int>(reported);
|
||||
if (usable >= bitCount) {
|
||||
return static_cast<DWORD_PTR>(~static_cast<DWORD_PTR>(0));
|
||||
}
|
||||
return (static_cast<DWORD_PTR>(1) << usable) - 1;
|
||||
}
|
||||
|
||||
DWORD_PTR g_processAffinityMask = 0;
|
||||
bool g_processAffinityMaskInitialized = false;
|
||||
} // namespace
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
HANDLE WIN_FUNC GetCurrentProcess() {
|
||||
DEBUG_LOG("GetCurrentProcess() -> %p\n", reinterpret_cast<void *>(static_cast<uintptr_t>(-1)));
|
||||
return reinterpret_cast<HANDLE>(static_cast<uintptr_t>(-1));
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetCurrentProcessId() {
|
||||
DWORD pid = static_cast<DWORD>(getpid());
|
||||
DEBUG_LOG("GetCurrentProcessId() -> %u\n", pid);
|
||||
return pid;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetCurrentThreadId() {
|
||||
pthread_t thread = pthread_self();
|
||||
const auto threadId = static_cast<DWORD>(thread);
|
||||
DEBUG_LOG("GetCurrentThreadId() -> %u\n", threadId);
|
||||
return threadId;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask,
|
||||
PDWORD_PTR lpSystemAffinityMask) {
|
||||
DEBUG_LOG("GetProcessAffinityMask(%p, %p, %p)\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
|
||||
if (!lpProcessAffinityMask || !lpSystemAffinityMask) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uintptr_t rawHandle = reinterpret_cast<uintptr_t>(hProcess);
|
||||
bool isPseudoHandle = rawHandle == static_cast<uintptr_t>(-1);
|
||||
if (!isPseudoHandle) {
|
||||
auto data = handles::dataFromHandle(hProcess, false);
|
||||
if (data.type != handles::TYPE_PROCESS || data.ptr == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD_PTR systemMask = computeSystemAffinityMask();
|
||||
if (!g_processAffinityMaskInitialized) {
|
||||
g_processAffinityMask = systemMask;
|
||||
g_processAffinityMaskInitialized = true;
|
||||
}
|
||||
DWORD_PTR processMask = g_processAffinityMask & systemMask;
|
||||
if (processMask == 0) {
|
||||
processMask = systemMask == 0 ? 1 : systemMask;
|
||||
}
|
||||
|
||||
*lpProcessAffinityMask = processMask;
|
||||
*lpSystemAffinityMask = systemMask == 0 ? 1 : systemMask;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask) {
|
||||
DEBUG_LOG("SetProcessAffinityMask(%p, 0x%lx)\n", hProcess, static_cast<unsigned long>(dwProcessAffinityMask));
|
||||
if (dwProcessAffinityMask == 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uintptr_t rawHandle = reinterpret_cast<uintptr_t>(hProcess);
|
||||
bool isPseudoHandle = rawHandle == static_cast<uintptr_t>(-1);
|
||||
if (!isPseudoHandle) {
|
||||
auto data = handles::dataFromHandle(hProcess, false);
|
||||
if (data.type != handles::TYPE_PROCESS) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD_PTR systemMask = computeSystemAffinityMask();
|
||||
if ((dwProcessAffinityMask & systemMask) == 0 || (dwProcessAffinityMask & ~systemMask) != 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_processAffinityMask = dwProcessAffinityMask & systemMask;
|
||||
g_processAffinityMaskInitialized = true;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void WIN_FUNC ExitProcess(UINT uExitCode) {
|
||||
DEBUG_LOG("ExitProcess(%u)\n", uExitCode);
|
||||
std::exit(static_cast<int>(uExitCode));
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC TerminateProcess(HANDLE hProcess, UINT uExitCode) {
|
||||
DEBUG_LOG("TerminateProcess(%p, %u)\n", hProcess, uExitCode);
|
||||
if (hProcess == reinterpret_cast<HANDLE>(static_cast<uintptr_t>(-1))) {
|
||||
ExitProcess(uExitCode);
|
||||
}
|
||||
auto data = handles::dataFromHandle(hProcess, false);
|
||||
if (data.type != handles::TYPE_PROCESS || data.ptr == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
auto *process = reinterpret_cast<processes::Process *>(data.ptr);
|
||||
if (kill(process->pid, SIGKILL) != 0) {
|
||||
int err = errno;
|
||||
DEBUG_LOG("TerminateProcess: kill(%d) failed: %s\n", process->pid, strerror(err));
|
||||
switch (err) {
|
||||
case ESRCH:
|
||||
case EPERM:
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
default:
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
process->forcedExitCode = uExitCode;
|
||||
process->terminationRequested = true;
|
||||
process->exitCode = uExitCode;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) {
|
||||
DEBUG_LOG("GetExitCodeProcess(%p, %p)\n", hProcess, lpExitCode);
|
||||
if (!lpExitCode) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto *process = processes::processFromHandle(hProcess, false);
|
||||
if (!process) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
*lpExitCode = process->exitCode;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||
DEBUG_LOG("CreateProcessA %s \"%s\" %p %p %d 0x%x %p %s %p %p\n", lpApplicationName ? lpApplicationName : "<null>",
|
||||
lpCommandLine ? lpCommandLine : "<null>", lpProcessAttributes, lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags, lpEnvironment, lpCurrentDirectory ? lpCurrentDirectory : "<none>", lpStartupInfo,
|
||||
lpProcessInformation);
|
||||
|
||||
bool useSearchPath = lpApplicationName == nullptr;
|
||||
std::string application;
|
||||
std::string commandLine = lpCommandLine ? lpCommandLine : "";
|
||||
if (lpApplicationName) {
|
||||
application = lpApplicationName;
|
||||
} else {
|
||||
std::vector<std::string> arguments = processes::splitCommandLine(commandLine.c_str());
|
||||
if (arguments.empty()) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return FALSE;
|
||||
}
|
||||
application = arguments.front();
|
||||
}
|
||||
|
||||
auto resolved = processes::resolveExecutable(application, useSearchPath);
|
||||
if (!resolved) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pid_t pid = -1;
|
||||
int spawnResult = processes::spawnWithCommandLine(*resolved, commandLine, &pid);
|
||||
if (spawnResult != 0) {
|
||||
wibo::lastError = (spawnResult == ENOENT) ? ERROR_FILE_NOT_FOUND : ERROR_ACCESS_DENIED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (lpProcessInformation) {
|
||||
lpProcessInformation->hProcess = processes::allocProcessHandle(pid);
|
||||
lpProcessInformation->hThread = nullptr;
|
||||
lpProcessInformation->dwProcessId = static_cast<DWORD>(pid);
|
||||
lpProcessInformation->dwThreadId = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
(void)lpProcessAttributes;
|
||||
(void)lpThreadAttributes;
|
||||
(void)bInheritHandles;
|
||||
(void)dwCreationFlags;
|
||||
(void)lpEnvironment;
|
||||
(void)lpCurrentDirectory;
|
||||
(void)lpStartupInfo;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||
std::string applicationUtf8;
|
||||
if (lpApplicationName) {
|
||||
applicationUtf8 = wideStringToString(lpApplicationName);
|
||||
}
|
||||
std::string commandUtf8;
|
||||
if (lpCommandLine) {
|
||||
commandUtf8 = wideStringToString(lpCommandLine);
|
||||
}
|
||||
std::string directoryUtf8;
|
||||
if (lpCurrentDirectory) {
|
||||
directoryUtf8 = wideStringToString(lpCurrentDirectory);
|
||||
}
|
||||
DEBUG_LOG("CreateProcessW %s \"%s\" %p %p %d 0x%x %p %s %p %p\n",
|
||||
applicationUtf8.empty() ? "<null>" : applicationUtf8.c_str(),
|
||||
commandUtf8.empty() ? "<null>" : commandUtf8.c_str(), lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags, lpEnvironment, directoryUtf8.empty() ? "<none>" : directoryUtf8.c_str(),
|
||||
lpStartupInfo, lpProcessInformation);
|
||||
std::vector<char> commandBuffer;
|
||||
if (!commandUtf8.empty()) {
|
||||
commandBuffer.assign(commandUtf8.begin(), commandUtf8.end());
|
||||
commandBuffer.push_back('\0');
|
||||
}
|
||||
LPSTR commandPtr = commandBuffer.empty() ? nullptr : commandBuffer.data();
|
||||
LPCSTR applicationPtr = applicationUtf8.empty() ? nullptr : applicationUtf8.c_str();
|
||||
LPCSTR directoryPtr = directoryUtf8.empty() ? nullptr : directoryUtf8.c_str();
|
||||
return CreateProcessA(applicationPtr, commandPtr, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags, lpEnvironment, directoryPtr, nullptr /* TODO: lpStartupInfo */,
|
||||
lpProcessInformation);
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
506
dll/kernel32/synchapi.cpp
Normal file
506
dll/kernel32/synchapi.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "kernel32.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
std::u16string makeMutexName(LPCWSTR name) {
|
||||
if (!name) {
|
||||
return {};
|
||||
}
|
||||
size_t len = wstrlen(reinterpret_cast<const uint16_t *>(name));
|
||||
return {reinterpret_cast<const char16_t *>(name), len};
|
||||
}
|
||||
|
||||
void makeWideNameFromAnsi(LPCSTR ansiName, std::vector<uint16_t> &outWide) {
|
||||
outWide.clear();
|
||||
if (!ansiName) {
|
||||
return;
|
||||
}
|
||||
outWide = stringToWideString(ansiName);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
namespace {
|
||||
|
||||
std::mutex mutexRegistryLock;
|
||||
std::unordered_map<std::u16string, MutexObject *> namedMutexes;
|
||||
|
||||
std::mutex eventRegistryLock;
|
||||
std::unordered_map<std::u16string, EventObject *> namedEvents;
|
||||
|
||||
std::mutex semaphoreRegistryLock;
|
||||
std::unordered_map<std::u16string, SemaphoreObject *> namedSemaphores;
|
||||
|
||||
EventObject *eventObjectFromHandle(HANDLE hEvent) {
|
||||
auto data = handles::dataFromHandle(hEvent, false);
|
||||
if (data.type != handles::TYPE_EVENT || data.ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<EventObject *>(data.ptr);
|
||||
}
|
||||
|
||||
SemaphoreObject *semaphoreObjectFromHandle(HANDLE hSemaphore) {
|
||||
auto data = handles::dataFromHandle(hSemaphore, false);
|
||||
if (data.type != handles::TYPE_SEMAPHORE || data.ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<SemaphoreObject *>(data.ptr);
|
||||
}
|
||||
|
||||
MutexObject *mutexObjectFromHandle(HANDLE hMutex) {
|
||||
auto data = handles::dataFromHandle(hMutex, false);
|
||||
if (data.type != handles::TYPE_MUTEX || data.ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<MutexObject *>(data.ptr);
|
||||
}
|
||||
|
||||
bool setEventSignaledState(HANDLE hEvent, bool signaled) {
|
||||
EventObject *obj = eventObjectFromHandle(hEvent);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
obj->signaled = signaled;
|
||||
if (signaled) {
|
||||
if (obj->manualReset) {
|
||||
pthread_cond_broadcast(&obj->cond);
|
||||
} else {
|
||||
pthread_cond_signal(&obj->cond);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void releaseMutexObject(MutexObject *obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mutexRegistryLock);
|
||||
obj->refCount--;
|
||||
if (obj->refCount == 0) {
|
||||
if (!obj->name.empty()) {
|
||||
namedMutexes.erase(obj->name);
|
||||
}
|
||||
pthread_mutex_destroy(&obj->mutex);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void releaseEventObject(EventObject *obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(eventRegistryLock);
|
||||
obj->refCount--;
|
||||
if (obj->refCount == 0) {
|
||||
if (!obj->name.empty()) {
|
||||
namedEvents.erase(obj->name);
|
||||
}
|
||||
pthread_cond_destroy(&obj->cond);
|
||||
pthread_mutex_destroy(&obj->mutex);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void releaseSemaphoreObject(SemaphoreObject *obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(semaphoreRegistryLock);
|
||||
obj->refCount--;
|
||||
if (obj->refCount == 0) {
|
||||
if (!obj->name.empty()) {
|
||||
namedSemaphores.erase(obj->name);
|
||||
}
|
||||
pthread_cond_destroy(&obj->cond);
|
||||
pthread_mutex_destroy(&obj->mutex);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName) {
|
||||
std::string nameLog;
|
||||
if (lpName) {
|
||||
nameLog = wideStringToString(reinterpret_cast<const uint16_t *>(lpName));
|
||||
} else {
|
||||
nameLog = "<unnamed>";
|
||||
}
|
||||
DEBUG_LOG("CreateMutexW(%p, %d, %s)\n", lpMutexAttributes, bInitialOwner, nameLog.c_str());
|
||||
(void)lpMutexAttributes;
|
||||
|
||||
std::u16string name = makeMutexName(lpName);
|
||||
MutexObject *obj = nullptr;
|
||||
bool alreadyExists = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutexRegistryLock);
|
||||
if (!name.empty()) {
|
||||
auto it = namedMutexes.find(name);
|
||||
if (it != namedMutexes.end()) {
|
||||
obj = it->second;
|
||||
obj->refCount++;
|
||||
alreadyExists = true;
|
||||
}
|
||||
}
|
||||
if (!obj) {
|
||||
obj = new MutexObject();
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&obj->mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
obj->name = name;
|
||||
if (!name.empty()) {
|
||||
namedMutexes[name] = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyExists && bInitialOwner) {
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
obj->owner = pthread_self();
|
||||
obj->ownerValid = true;
|
||||
obj->recursionCount = 1;
|
||||
}
|
||||
|
||||
HANDLE handle = handles::allocDataHandle({handles::TYPE_MUTEX, obj, 0});
|
||||
wibo::lastError = alreadyExists ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS;
|
||||
return handle;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName) {
|
||||
DEBUG_LOG("CreateMutexA -> ");
|
||||
std::vector<uint16_t> wideName;
|
||||
makeWideNameFromAnsi(lpName, wideName);
|
||||
return CreateMutexW(lpMutexAttributes, bInitialOwner,
|
||||
lpName ? reinterpret_cast<LPCWSTR>(wideName.data()) : nullptr);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC ReleaseMutex(HANDLE hMutex) {
|
||||
DEBUG_LOG("ReleaseMutex(%p)\n", hMutex);
|
||||
MutexObject *obj = mutexObjectFromHandle(hMutex);
|
||||
if (!obj) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
pthread_t self = pthread_self();
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
if (!obj->ownerValid || !pthread_equal(obj->owner, self) || obj->recursionCount == 0) {
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
wibo::lastError = ERROR_NOT_OWNER;
|
||||
return FALSE;
|
||||
}
|
||||
obj->recursionCount--;
|
||||
if (obj->recursionCount == 0) {
|
||||
obj->ownerValid = false;
|
||||
}
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
|
||||
LPCWSTR lpName) {
|
||||
std::string nameLog;
|
||||
if (lpName) {
|
||||
nameLog = wideStringToString(reinterpret_cast<const uint16_t *>(lpName));
|
||||
} else {
|
||||
nameLog = "<unnamed>";
|
||||
}
|
||||
DEBUG_LOG("CreateEventW(name=%s, manualReset=%d, initialState=%d)\n", nameLog.c_str(), bManualReset, bInitialState);
|
||||
(void)lpEventAttributes;
|
||||
|
||||
std::u16string name = makeMutexName(lpName);
|
||||
EventObject *obj = nullptr;
|
||||
bool alreadyExists = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(eventRegistryLock);
|
||||
if (!name.empty()) {
|
||||
auto it = namedEvents.find(name);
|
||||
if (it != namedEvents.end()) {
|
||||
obj = it->second;
|
||||
obj->refCount++;
|
||||
alreadyExists = true;
|
||||
}
|
||||
}
|
||||
if (!obj) {
|
||||
obj = new EventObject();
|
||||
pthread_mutex_init(&obj->mutex, nullptr);
|
||||
pthread_cond_init(&obj->cond, nullptr);
|
||||
obj->manualReset = bManualReset;
|
||||
obj->signaled = bInitialState;
|
||||
obj->name = name;
|
||||
if (!name.empty()) {
|
||||
namedEvents[name] = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE handle = handles::allocDataHandle({handles::TYPE_EVENT, obj, 0});
|
||||
wibo::lastError = alreadyExists ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS;
|
||||
return handle;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
|
||||
LPCSTR lpName) {
|
||||
DEBUG_LOG("CreateEventA -> ");
|
||||
std::vector<uint16_t> wideName;
|
||||
makeWideNameFromAnsi(lpName, wideName);
|
||||
return CreateEventW(lpEventAttributes, bManualReset, bInitialState,
|
||||
lpName ? reinterpret_cast<LPCWSTR>(wideName.data()) : nullptr);
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCWSTR lpName) {
|
||||
DEBUG_LOG("CreateSemaphoreW(%p, %ld, %ld, %ls)\n", lpSemaphoreAttributes, static_cast<long>(lInitialCount),
|
||||
static_cast<long>(lMaximumCount), lpName ? reinterpret_cast<const wchar_t *>(lpName) : L"<null>");
|
||||
(void)lpSemaphoreAttributes;
|
||||
|
||||
std::u16string name = makeMutexName(lpName);
|
||||
SemaphoreObject *obj = nullptr;
|
||||
bool alreadyExists = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(semaphoreRegistryLock);
|
||||
if (!name.empty()) {
|
||||
auto it = namedSemaphores.find(name);
|
||||
if (it != namedSemaphores.end()) {
|
||||
obj = it->second;
|
||||
obj->refCount++;
|
||||
alreadyExists = true;
|
||||
}
|
||||
}
|
||||
if (!obj) {
|
||||
if (lMaximumCount <= 0 || lInitialCount < 0 || lInitialCount > lMaximumCount) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return nullptr;
|
||||
}
|
||||
obj = new SemaphoreObject();
|
||||
pthread_mutex_init(&obj->mutex, nullptr);
|
||||
pthread_cond_init(&obj->cond, nullptr);
|
||||
obj->count = lInitialCount;
|
||||
obj->maxCount = lMaximumCount;
|
||||
obj->name = name;
|
||||
if (!name.empty()) {
|
||||
namedSemaphores[name] = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE handle = handles::allocDataHandle({handles::TYPE_SEMAPHORE, obj, 0});
|
||||
wibo::lastError = alreadyExists ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS;
|
||||
return handle;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCSTR lpName) {
|
||||
DEBUG_LOG("CreateSemaphoreA -> ");
|
||||
std::vector<uint16_t> wideName;
|
||||
makeWideNameFromAnsi(lpName, wideName);
|
||||
return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount,
|
||||
lpName ? reinterpret_cast<LPCWSTR>(wideName.data()) : nullptr);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, PLONG lpPreviousCount) {
|
||||
DEBUG_LOG("ReleaseSemaphore(%p, %ld, %p)\n", hSemaphore, static_cast<long>(lReleaseCount), lpPreviousCount);
|
||||
if (lReleaseCount <= 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
SemaphoreObject *obj = semaphoreObjectFromHandle(hSemaphore);
|
||||
if (!obj) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
if (lpPreviousCount) {
|
||||
*lpPreviousCount = obj->count;
|
||||
}
|
||||
if (lReleaseCount > obj->maxCount - obj->count) {
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
obj->count += lReleaseCount;
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
pthread_cond_broadcast(&obj->cond);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetEvent(HANDLE hEvent) {
|
||||
DEBUG_LOG("SetEvent(%p)\n", hEvent);
|
||||
if (!setEventSignaledState(hEvent, true)) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC ResetEvent(HANDLE hEvent) {
|
||||
DEBUG_LOG("ResetEvent(%p)\n", hEvent);
|
||||
if (!setEventSignaledState(hEvent, false)) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) {
|
||||
DEBUG_LOG("WaitForSingleObject(%p, %u)\n", hHandle, dwMilliseconds);
|
||||
handles::Data data = handles::dataFromHandle(hHandle, false);
|
||||
switch (data.type) {
|
||||
case handles::TYPE_PROCESS: {
|
||||
if (dwMilliseconds != INFINITE) {
|
||||
DEBUG_LOG("WaitForSingleObject: timeout for process not supported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
auto *process = reinterpret_cast<processes::Process *>(data.ptr);
|
||||
int status = 0;
|
||||
for (;;) {
|
||||
if (waitpid(process->pid, &status, 0) == -1) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
if (errno == ECHILD && process->terminationRequested) {
|
||||
process->exitCode = process->forcedExitCode;
|
||||
break;
|
||||
}
|
||||
DEBUG_LOG("WaitForSingleObject: waitpid(%d) failed: %s\n", process->pid, strerror(errno));
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (process->terminationRequested) {
|
||||
process->exitCode = process->forcedExitCode;
|
||||
} else if (WIFEXITED(status)) {
|
||||
process->exitCode = static_cast<DWORD>(WEXITSTATUS(status));
|
||||
} else {
|
||||
DEBUG_LOG("WaitForSingleObject: child process exited abnormally - returning exit code 1\n");
|
||||
process->exitCode = 1;
|
||||
}
|
||||
process->terminationRequested = false;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
case handles::TYPE_EVENT: {
|
||||
EventObject *obj = reinterpret_cast<EventObject *>(data.ptr);
|
||||
if (dwMilliseconds != INFINITE) {
|
||||
DEBUG_LOG("WaitForSingleObject: timeout for event not supported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
while (!obj->signaled) {
|
||||
pthread_cond_wait(&obj->cond, &obj->mutex);
|
||||
}
|
||||
if (!obj->manualReset) {
|
||||
obj->signaled = false;
|
||||
}
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
case handles::TYPE_THREAD: {
|
||||
ThreadObject *obj = reinterpret_cast<ThreadObject *>(data.ptr);
|
||||
if (dwMilliseconds != INFINITE) {
|
||||
DEBUG_LOG("WaitForSingleObject: timeout for thread not supported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
while (!obj->finished) {
|
||||
pthread_cond_wait(&obj->cond, &obj->mutex);
|
||||
}
|
||||
bool needJoin = !obj->joined && !obj->detached;
|
||||
pthread_t thread = obj->thread;
|
||||
if (needJoin) {
|
||||
obj->joined = true;
|
||||
}
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
if (needJoin) {
|
||||
pthread_join(thread, nullptr);
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
case handles::TYPE_SEMAPHORE: {
|
||||
SemaphoreObject *obj = reinterpret_cast<SemaphoreObject *>(data.ptr);
|
||||
if (dwMilliseconds != INFINITE) {
|
||||
DEBUG_LOG("WaitForSingleObject: timeout for semaphore not supported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
while (obj->count == 0) {
|
||||
pthread_cond_wait(&obj->cond, &obj->mutex);
|
||||
}
|
||||
obj->count--;
|
||||
pthread_mutex_unlock(&obj->mutex);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
case handles::TYPE_MUTEX: {
|
||||
MutexObject *obj = reinterpret_cast<MutexObject *>(data.ptr);
|
||||
if (dwMilliseconds != INFINITE) {
|
||||
DEBUG_LOG("WaitForSingleObject: timeout for mutex not supported\n");
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
pthread_mutex_lock(&obj->mutex);
|
||||
pthread_t self = pthread_self();
|
||||
if (obj->ownerValid && pthread_equal(obj->owner, self)) {
|
||||
obj->recursionCount++;
|
||||
} else {
|
||||
obj->owner = self;
|
||||
obj->ownerValid = true;
|
||||
obj->recursionCount = 1;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
default:
|
||||
DEBUG_LOG("WaitForSingleObject: unsupported handle type %d\n", data.type);
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void resetOverlappedEvent(OVERLAPPED *ov) {
|
||||
if (!ov || !ov->hEvent) {
|
||||
return;
|
||||
}
|
||||
setEventSignaledState(ov->hEvent, false);
|
||||
}
|
||||
|
||||
void signalOverlappedEvent(OVERLAPPED *ov) {
|
||||
if (!ov || !ov->hEvent) {
|
||||
return;
|
||||
}
|
||||
setEventSignaledState(ov->hEvent, true);
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
58
dll/kernel32/sysinfoapi.cpp
Normal file
58
dll/kernel32/sysinfoapi.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "common.h"
|
||||
#include "kernel32.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_INTEL = 0;
|
||||
constexpr DWORD PROCESSOR_INTEL_PENTIUM = 586;
|
||||
|
||||
DWORD_PTR computeSystemProcessorMask(unsigned int cpuCount) {
|
||||
const auto maskWidth = static_cast<unsigned int>(sizeof(DWORD_PTR) * 8);
|
||||
if (cpuCount >= maskWidth) {
|
||||
return static_cast<DWORD_PTR>(~static_cast<DWORD_PTR>(0));
|
||||
}
|
||||
DWORD_PTR mask = (static_cast<DWORD_PTR>(1) << cpuCount) - 1;
|
||||
return mask == 0 ? 1 : mask;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
void WIN_FUNC GetSystemInfo(LPSYSTEM_INFO lpSystemInfo) {
|
||||
DEBUG_LOG("GetSystemInfo(%p)\n", lpSystemInfo);
|
||||
if (!lpSystemInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::memset(lpSystemInfo, 0, sizeof(*lpSystemInfo));
|
||||
lpSystemInfo->wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
|
||||
lpSystemInfo->dwOemId = lpSystemInfo->wProcessorArchitecture;
|
||||
lpSystemInfo->dwProcessorType = PROCESSOR_INTEL_PENTIUM;
|
||||
lpSystemInfo->wProcessorLevel = 6; // Pentium
|
||||
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
if (pageSize <= 0) {
|
||||
pageSize = 4096;
|
||||
}
|
||||
lpSystemInfo->dwPageSize = static_cast<DWORD>(pageSize);
|
||||
|
||||
lpSystemInfo->lpMinimumApplicationAddress = reinterpret_cast<LPVOID>(0x00010000);
|
||||
if (sizeof(void *) == 4) {
|
||||
lpSystemInfo->lpMaximumApplicationAddress = reinterpret_cast<LPVOID>(0x7FFEFFFF);
|
||||
} else {
|
||||
lpSystemInfo->lpMaximumApplicationAddress = reinterpret_cast<LPVOID>(0x00007FFFFFFEFFFFull);
|
||||
}
|
||||
|
||||
unsigned int cpuCount = 1;
|
||||
long reported = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (reported > 0) {
|
||||
cpuCount = static_cast<unsigned int>(reported);
|
||||
}
|
||||
lpSystemInfo->dwNumberOfProcessors = cpuCount;
|
||||
lpSystemInfo->dwActiveProcessorMask = computeSystemProcessorMask(cpuCount);
|
||||
|
||||
lpSystemInfo->dwAllocationGranularity = 0x10000;
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
50
dll/kernel32/wow64apiset.cpp
Normal file
50
dll/kernel32/wow64apiset.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "kernel32.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC Wow64DisableWow64FsRedirection(PVOID *OldValue) {
|
||||
DEBUG_LOG("STUB: Wow64DisableWow64FsRedirection(%p)\n", OldValue);
|
||||
if (OldValue) {
|
||||
*OldValue = nullptr;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC Wow64RevertWow64FsRedirection(PVOID OldValue) {
|
||||
DEBUG_LOG("STUB: Wow64RevertWow64FsRedirection(%p)\n", OldValue);
|
||||
(void)OldValue;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC IsWow64Process(HANDLE hProcess, PBOOL Wow64Process) {
|
||||
DEBUG_LOG("IsWow64Process(%p, %p)\n", hProcess, Wow64Process);
|
||||
if (!Wow64Process) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const auto rawHandle = reinterpret_cast<uintptr_t>(hProcess);
|
||||
bool isPseudoHandle = rawHandle == static_cast<uintptr_t>(-1);
|
||||
if (!isPseudoHandle) {
|
||||
if (!hProcess) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
auto data = handles::dataFromHandle(hProcess, false);
|
||||
if (data.type != handles::TYPE_PROCESS || data.ptr == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*Wow64Process = FALSE;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
Loading…
x
Reference in New Issue
Block a user