clean up and standardize types across the codebase, unify atomic operations, improve UTF-8 handling throughout the system, remove obsolete input and named queue interfaces, redesign process preparation and creation, tighten IPC and service boundaries, improve error handling and reliability, minor documentation cleanup, fix doom surfaces, fix panic in ini parsing.
This commit is contained in:
1 parent
899225f551
commit
c0ad63c27f
226 files changed
+6562
-4147
No files matched your search
@@ -16,6 +16,7 @@
|
||||
// - File I/O resolves Win32 paths in userspace, then uses capability-relative
|
||||
// opens plus the common read/write/seek/query/close syscalls.
|
||||
|
||||
#include <ntlite/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -45,7 +46,15 @@ typedef long LONG;
|
||||
typedef struct { LONG x; LONG y; } POINT;
|
||||
typedef struct { SHORT X; SHORT Y; } COORD;
|
||||
typedef struct { SHORT Left; SHORT Top; SHORT Right; SHORT Bottom; } SMALL_RECT;
|
||||
typedef struct { uintptr_t _opaque[5]; } CRITICAL_SECTION;
|
||||
typedef struct {
|
||||
int32_t Lock;
|
||||
uint32_t LockPadding;
|
||||
uintptr_t Owner;
|
||||
uintptr_t Recursion;
|
||||
uintptr_t Reserved[2];
|
||||
} CRITICAL_SECTION;
|
||||
_Static_assert(sizeof(CRITICAL_SECTION) == sizeof(uintptr_t) * 5u,
|
||||
"Win64 CRITICAL_SECTION compatibility storage must remain five pointers");
|
||||
typedef struct { void* _ptr; } CONDITION_VARIABLE;
|
||||
|
||||
// Forward declarations used by the process-local GetProcAddress surface.
|
||||
@@ -271,7 +280,7 @@ static void TranslatePath(const char* input, char* output) {
|
||||
}
|
||||
|
||||
// Implements the k32 Open File Native operation.
|
||||
static uint32_t K32OpenFileNative(const char* path,
|
||||
static KSTATUS K32OpenFileNative(const char* path,
|
||||
uint32_t access,
|
||||
uint32_t disposition,
|
||||
uint32_t* handleOut) {
|
||||
@@ -279,25 +288,25 @@ static uint32_t K32OpenFileNative(const char* path,
|
||||
}
|
||||
|
||||
// Implements the k32 Delete File Native operation.
|
||||
static uint32_t K32DeleteFileNative(const char* path) {
|
||||
static KSTATUS K32DeleteFileNative(const char* path) {
|
||||
return NtlDeleteFile(SysSvFromCstr(path));
|
||||
}
|
||||
|
||||
// Implements the k32 Open Dir Native operation.
|
||||
static uint32_t K32OpenDirNative(const char* path, uint32_t* handleOut) {
|
||||
static KSTATUS K32OpenDirNative(const char* path, uint32_t* handleOut) {
|
||||
return NtlOpenDir(SysSvFromCstr(path), SYS_DIR_ACCESS_ENUMERATE | SYS_DIR_ACCESS_OPEN,
|
||||
SYS_DIR_FLAG_NONE, handleOut);
|
||||
}
|
||||
|
||||
// Implements the k32 Set Cwd Native operation.
|
||||
static uint32_t K32SetCwdNative(const char* path) {
|
||||
static KSTATUS K32SetCwdNative(const char* path) {
|
||||
return NtlSetCurrentDirectory(SysSvFromCstr(path));
|
||||
}
|
||||
|
||||
// Implements the k32 Get Cwd Native operation.
|
||||
static uint32_t K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut) {
|
||||
static KSTATUS K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut) {
|
||||
size_t required = 0;
|
||||
uint32_t status = NtlGetCurrentDirectory(buffer, capacity, &required);
|
||||
KSTATUS status = NtlGetCurrentDirectory(buffer, capacity, &required);
|
||||
if (lengthOut) *lengthOut = required ? required - 1u : 0;
|
||||
return status;
|
||||
}
|
||||
@@ -308,7 +317,7 @@ static KSTATUS K32ResolveModuleName(void* context, SYS_STRING_VIEW requested, SY
|
||||
}
|
||||
|
||||
// Translates Win32 process syntax into native resource/CWD syntax.
|
||||
static uint32_t K32ProcessPath(const char* input, char* output, size_t outputSize) {
|
||||
static KSTATUS K32ProcessPath(const char* input, char* output, size_t outputSize) {
|
||||
if (!input || !output || outputSize == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
char translated[MAX_PATH];
|
||||
TranslatePath(input, translated);
|
||||
@@ -320,9 +329,9 @@ static uint32_t K32ProcessPath(const char* input, char* output, size_t outputSiz
|
||||
}
|
||||
|
||||
// Creates one Win32 child through RSSRV lookup plus the userspace PE loader.
|
||||
static uint32_t K32CreateProcessNative(const char* path, uint32_t imageFile, uint32_t* handleOut, const char* commandLine, const char* currentDirectory) {
|
||||
static KSTATUS K32CreateProcessNative(const char* path, uint32_t imageFile, uint32_t* handleOut, const char* commandLine, const char* currentDirectory) {
|
||||
char relative[MAX_PATH];
|
||||
uint32_t status = K32ProcessPath(path, relative, sizeof(relative));
|
||||
KSTATUS status = K32ProcessPath(path, relative, sizeof(relative));
|
||||
if (status != NTLSTATUS_SUCCESS) return status;
|
||||
NTL_CREATE_SYSTEM_PROCESS_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
@@ -619,7 +628,7 @@ __declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize,
|
||||
__declspec(dllexport) BOOL VirtualFree(void* lpAddress, size_t dwSize, DWORD dwFreeType) {
|
||||
(void)dwSize; (void)dwFreeType;
|
||||
if (!lpAddress) return TRUE;
|
||||
uint32_t s = SysFreeVm(lpAddress);
|
||||
KSTATUS s = SysFreeVm(lpAddress);
|
||||
if (s != NTLSTATUS_SUCCESS) { gLastError = 87; return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
@@ -629,7 +638,7 @@ __declspec(dllexport) BOOL VirtualProtect(void* lpAddress, size_t dwSize,
|
||||
if (!lpAddress || !dwSize) { gLastError = 87; return FALSE; }
|
||||
size_t pages = (dwSize + 4095u) / 4096u;
|
||||
uint32_t oldSysProtect = 0;
|
||||
uint32_t s = SysProtectVm(lpAddress, pages, WinProtectToSysVm(flNewProtect),
|
||||
KSTATUS s = SysProtectVm(lpAddress, pages, WinProtectToSysVm(flNewProtect),
|
||||
lpflOldProtect ? &oldSysProtect : NULL);
|
||||
if (s != NTLSTATUS_SUCCESS) { gLastError = 87; return FALSE; }
|
||||
if (lpflOldProtect) *lpflOldProtect = SysProtectVmToWin(oldSysProtect);
|
||||
@@ -645,7 +654,7 @@ __declspec(dllexport) size_t VirtualQuery(const void* lpAddress,
|
||||
}
|
||||
|
||||
SYS_VM_REGION_INFO info;
|
||||
uint32_t s = SysQueryVm((void*)lpAddress, &info);
|
||||
KSTATUS s = SysQueryVm((void*)lpAddress, &info);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
gLastError = 87;
|
||||
return 0;
|
||||
@@ -682,7 +691,7 @@ __declspec(dllexport) HANDLE CreateFileMappingA(HANDLE hFile,
|
||||
WinFileMappingProtectToSysVm(flProtect), SYS_MAP_FLAG_NONE,
|
||||
maximumSize, &kh
|
||||
};
|
||||
uint32_t s = SysCreateFileMapping(&createMapping);
|
||||
KSTATUS s = SysCreateFileMapping(&createMapping);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
gLastError = (s == NTLSTATUS_NOT_SUPPORTED) ? 120 : ((s == NTLSTATUS_NO_MEMORY) ? 8 : 87);
|
||||
return NULL;
|
||||
@@ -718,7 +727,7 @@ __declspec(dllexport) void* MapViewOfFile(HANDLE hFileMappingObject,
|
||||
WinFileMapAccessToSys(dwDesiredAccess), SYS_MAP_FLAG_NONE,
|
||||
offset, dwNumberOfBytesToMap, &base
|
||||
};
|
||||
uint32_t s = SysMapFile(&mapFile);
|
||||
KSTATUS s = SysMapFile(&mapFile);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
gLastError = (s == NTLSTATUS_NOT_SUPPORTED) ? 120 : ((s == NTLSTATUS_NO_MEMORY) ? 8 : 87);
|
||||
return NULL;
|
||||
@@ -728,7 +737,7 @@ __declspec(dllexport) void* MapViewOfFile(HANDLE hFileMappingObject,
|
||||
|
||||
__declspec(dllexport) BOOL UnmapViewOfFile(const void* lpBaseAddress) {
|
||||
if (!lpBaseAddress) { gLastError = 87; return FALSE; }
|
||||
uint32_t s = SysFreeVm((void*)lpBaseAddress);
|
||||
KSTATUS s = SysFreeVm((void*)lpBaseAddress);
|
||||
if (s != NTLSTATUS_SUCCESS) { gLastError = 87; return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
@@ -909,7 +918,7 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
|
||||
}
|
||||
|
||||
uint32_t kh = 0;
|
||||
uint32_t s = K32OpenFileNative(translatedName, sysAccess, sysDisposition, &kh);
|
||||
KSTATUS s = K32OpenFileNative(translatedName, sysAccess, sysDisposition, &kh);
|
||||
if (s != 0) {
|
||||
gLastError = (s == NTLSTATUS_OBJECT_NAME_COLLISION) ? 80 :
|
||||
(s == NTLSTATUS_NOT_FOUND) ? 2 : 5;
|
||||
@@ -924,7 +933,7 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
|
||||
__declspec(dllexport) DWORD GetFileSize(HANDLE hFile, DWORD* fileSizeHigh) {
|
||||
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return 0xFFFFFFFFUL; }
|
||||
uint64_t sz = 0;
|
||||
uint32_t s = SysGetFileSize(HANDLE_TO_KH(hFile), &sz);
|
||||
KSTATUS s = SysGetFileSize(HANDLE_TO_KH(hFile), &sz);
|
||||
if (s != 0) { gLastError = 6; return 0xFFFFFFFFUL; }
|
||||
if (fileSizeHigh) *fileSizeHigh = (DWORD)(sz >> 32);
|
||||
return (DWORD)(sz & 0xFFFFFFFFULL);
|
||||
@@ -942,7 +951,7 @@ __declspec(dllexport) BOOL ReadFile(HANDLE hFile, void* buf, DWORD toRead,
|
||||
|
||||
size_t got = 0;
|
||||
SYS_FILE_IO_REQUEST req = SysMakeFileIoRequest(HANDLE_TO_KH(hFile), buf, (size_t)toRead, &got);
|
||||
uint32_t s = SysReadFile(&req);
|
||||
KSTATUS s = SysReadFile(&req);
|
||||
if (bytesRead) *bytesRead = (DWORD)got;
|
||||
|
||||
if (s != 0) {
|
||||
@@ -967,7 +976,7 @@ __declspec(dllexport) BOOL WriteFile(HANDLE hFile, const void* buf, DWORD toWrit
|
||||
if (!hFile || hFile == INVALID_HANDLE_VALUE || !buf) { gLastError = 6; return FALSE; }
|
||||
size_t written = 0;
|
||||
SYS_FILE_IO_REQUEST req = SysMakeFileIoRequest(HANDLE_TO_KH(hFile), buf, (size_t)toWrite, &written);
|
||||
uint32_t s = SysWriteFile(&req);
|
||||
KSTATUS s = SysWriteFile(&req);
|
||||
if (bytesWritten) *bytesWritten = (DWORD)written;
|
||||
if (s != 0) { gLastError = 29; return FALSE; } // ERROR_WRITE_FAULT
|
||||
return TRUE;
|
||||
@@ -996,12 +1005,12 @@ __declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
|
||||
target = delta;
|
||||
} else if (method == FILE_CURRENT) {
|
||||
uint64_t cur = 0;
|
||||
uint32_t s = SysGetFilePos(kh, &cur);
|
||||
KSTATUS s = SysGetFilePos(kh, &cur);
|
||||
if (s != 0 || cur > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
|
||||
target = (int64_t)cur + delta;
|
||||
} else if (method == FILE_END) {
|
||||
uint64_t sz = 0;
|
||||
uint32_t s = SysGetFileSize(kh, &sz);
|
||||
KSTATUS s = SysGetFileSize(kh, &sz);
|
||||
if (s != 0 || sz > 0x7FFFFFFFFFFFFFFFULL) { gLastError = 6; return 0xFFFFFFFFUL; }
|
||||
target = (int64_t)sz + delta;
|
||||
} else {
|
||||
@@ -1014,7 +1023,7 @@ __declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
|
||||
}
|
||||
|
||||
uint64_t offset = (uint64_t)target;
|
||||
uint32_t s = SysSeekFile(kh, offset);
|
||||
KSTATUS s = SysSeekFile(kh, offset);
|
||||
if (s != 0) { gLastError = 1; return 0xFFFFFFFFUL; }
|
||||
if (distHigh) *distHigh = (long)(int32_t)(offset >> 32);
|
||||
return (DWORD)(offset & 0xFFFFFFFFULL);
|
||||
@@ -1025,7 +1034,7 @@ __declspec(dllexport) BOOL SetEndOfFile(HANDLE hFile) {
|
||||
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return FALSE; }
|
||||
uint32_t kh = HANDLE_TO_KH(hFile);
|
||||
uint64_t pos = 0;
|
||||
uint32_t s = SysGetFilePos(kh, &pos);
|
||||
KSTATUS s = SysGetFilePos(kh, &pos);
|
||||
if (s != 0) { gLastError = 6; return FALSE; }
|
||||
s = SysTruncateFile(kh, pos);
|
||||
if (s != 0) { gLastError = 1; return FALSE; }
|
||||
@@ -1049,38 +1058,38 @@ __declspec(dllexport) BOOL DeleteFileA(const char* lpFileName) {
|
||||
typedef struct K32_MUTEX_HANDLE {
|
||||
struct K32_MUTEX_HANDLE* Next;
|
||||
uint32_t Magic;
|
||||
volatile long StateLock;
|
||||
volatile long ApiUsers;
|
||||
int32_t StateLock;
|
||||
int32_t ApiUsers;
|
||||
uint32_t NativeHandle;
|
||||
DWORD OwnerTid;
|
||||
uint32_t Recursion;
|
||||
uint32_t Waiters;
|
||||
volatile long Closing;
|
||||
int32_t Closing;
|
||||
} K32_MUTEX_HANDLE;
|
||||
|
||||
static K32_MUTEX_HANDLE* gK32MutexRegistry;
|
||||
static volatile long gK32MutexRegistryLock;
|
||||
static int32_t gK32MutexRegistryLock;
|
||||
|
||||
// Acquires one short process-local mutex registry lock.
|
||||
static void K32MutexRegistryLock(void) {
|
||||
while (_InterlockedCompareExchange(&gK32MutexRegistryLock, 1, 0) != 0)
|
||||
while (NtlAtomicCompareExchange32(&gK32MutexRegistryLock, 1, 0) != 0)
|
||||
(void)SysYield();
|
||||
}
|
||||
|
||||
// Releases the process-local mutex registry lock.
|
||||
static void K32MutexRegistryUnlock(void) {
|
||||
_InterlockedExchange(&gK32MutexRegistryLock, 0);
|
||||
NtlAtomicExchange32(&gK32MutexRegistryLock, 0);
|
||||
}
|
||||
|
||||
// Acquires one short mutex-wrapper state lock.
|
||||
static void K32MutexStateLock(K32_MUTEX_HANDLE* mutex) {
|
||||
while (_InterlockedCompareExchange(&mutex->StateLock, 1, 0) != 0)
|
||||
while (NtlAtomicCompareExchange32(&mutex->StateLock, 1, 0) != 0)
|
||||
(void)SysYield();
|
||||
}
|
||||
|
||||
// Releases one mutex-wrapper state lock.
|
||||
static void K32MutexStateUnlock(K32_MUTEX_HANDLE* mutex) {
|
||||
_InterlockedExchange(&mutex->StateLock, 0);
|
||||
NtlAtomicExchange32(&mutex->StateLock, 0);
|
||||
}
|
||||
|
||||
// Registers one process-local Win32 mutex wrapper.
|
||||
@@ -1100,8 +1109,8 @@ static K32_MUTEX_HANDLE* K32ReferenceMutex(HANDLE handle) {
|
||||
current = current->Next) {
|
||||
if ((HANDLE)current == handle &&
|
||||
current->Magic == K32_MUTEX_MAGIC &&
|
||||
_InterlockedCompareExchange(¤t->Closing, 0, 0) == 0) {
|
||||
_InterlockedIncrement(¤t->ApiUsers);
|
||||
NtlAtomicLoad32(¤t->Closing) == 0) {
|
||||
NtlAtomicIncrement32(¤t->ApiUsers);
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
@@ -1113,7 +1122,7 @@ static K32_MUTEX_HANDLE* K32ReferenceMutex(HANDLE handle) {
|
||||
// Releases one mutex-wrapper API reference.
|
||||
static void K32DereferenceMutex(K32_MUTEX_HANDLE* mutex) {
|
||||
if (mutex)
|
||||
_InterlockedDecrement(&mutex->ApiUsers);
|
||||
NtlAtomicDecrement32(&mutex->ApiUsers);
|
||||
}
|
||||
|
||||
// Removes one mutex wrapper so no new API references can be acquired.
|
||||
@@ -1138,7 +1147,7 @@ static BOOL K32RemoveMutex(K32_MUTEX_HANDLE* mutex) {
|
||||
static DWORD K32WaitMutex(K32_MUTEX_HANDLE* mutex, DWORD milliseconds) {
|
||||
DWORD tid = K32CurrentTidOrOne();
|
||||
K32MutexStateLock(mutex);
|
||||
if (_InterlockedCompareExchange(&mutex->Closing, 0, 0) != 0) {
|
||||
if (NtlAtomicLoad32(&mutex->Closing) != 0) {
|
||||
K32MutexStateUnlock(mutex);
|
||||
gLastError = 6;
|
||||
return 0xFFFFFFFFUL;
|
||||
@@ -1159,7 +1168,7 @@ static DWORD K32WaitMutex(K32_MUTEX_HANDLE* mutex, DWORD milliseconds) {
|
||||
uint64_t timeout = milliseconds == 0xFFFFFFFFUL
|
||||
? SYS_WAIT_TIMEOUT_INFINITE
|
||||
: (uint64_t)milliseconds;
|
||||
uint32_t status = SysWaitSingle(mutex->NativeHandle, SYS_WAIT_FLAG_NONE, timeout);
|
||||
KSTATUS status = SysWaitSingle(mutex->NativeHandle, SYS_WAIT_FLAG_NONE, timeout);
|
||||
|
||||
K32MutexStateLock(mutex);
|
||||
if (mutex->Waiters)
|
||||
@@ -1184,7 +1193,7 @@ static DWORD K32WaitMutex(K32_MUTEX_HANDLE* mutex, DWORD milliseconds) {
|
||||
static BOOL K32CloseMutex(K32_MUTEX_HANDLE* mutex) {
|
||||
K32MutexStateLock(mutex);
|
||||
BOOL busy = mutex->OwnerTid != 0 || mutex->Waiters != 0;
|
||||
if (!busy && _InterlockedCompareExchange(&mutex->Closing, 1, 0) != 0)
|
||||
if (!busy && NtlAtomicCompareExchange32(&mutex->Closing, 1, 0) != 0)
|
||||
busy = TRUE;
|
||||
K32MutexStateUnlock(mutex);
|
||||
if (busy) {
|
||||
@@ -1198,9 +1207,9 @@ static BOOL K32CloseMutex(K32_MUTEX_HANDLE* mutex) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (mutex->ApiUsers > 1)
|
||||
while (NtlAtomicLoad32(&mutex->ApiUsers) > 1)
|
||||
(void)SysYield();
|
||||
uint32_t status = SysCloseHandle(mutex->NativeHandle);
|
||||
KSTATUS status = SysCloseHandle(mutex->NativeHandle);
|
||||
mutex->Magic = 0;
|
||||
K32DereferenceMutex(mutex);
|
||||
free(mutex);
|
||||
@@ -1222,7 +1231,7 @@ __declspec(dllexport) BOOL CloseHandle(HANDLE hObject) {
|
||||
if (mutex)
|
||||
return K32CloseMutex(mutex);
|
||||
|
||||
uint32_t status = SysCloseHandle(HANDLE_TO_KH(hObject));
|
||||
KSTATUS status = SysCloseHandle(HANDLE_TO_KH(hObject));
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
gLastError = 6;
|
||||
return FALSE;
|
||||
@@ -1387,7 +1396,7 @@ __declspec(dllexport) HANDLE LoadLibraryA(const char* lpLibFileName) {
|
||||
if (!lpLibFileName || !lpLibFileName[0]) { gLastError = 87; return NULL; }
|
||||
|
||||
SYS_HANDLE root = SYS_HANDLE_INVALID;
|
||||
uint32_t status = NtlResourceOpenSystemRoot(SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &root);
|
||||
KSTATUS status = NtlResourceOpenSystemRoot(SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN, &root);
|
||||
if (status != NTLSTATUS_SUCCESS) { gLastError = 126; return NULL; }
|
||||
|
||||
char relative[MAX_PATH];
|
||||
@@ -1454,7 +1463,7 @@ __declspec(dllexport) void* GetProcAddress(HANDLE hModule, const char* lpProcNam
|
||||
|
||||
if (hModule != WIN32_HMODULE_WIN32) {
|
||||
uintptr_t address = 0;
|
||||
uint32_t status = NtlGetModuleExport((NTL_MODULE_HANDLE)(uintptr_t)hModule,
|
||||
KSTATUS status = NtlGetModuleExport((NTL_MODULE_HANDLE)(uintptr_t)hModule,
|
||||
SysSvFromCstr(lpProcName), &address);
|
||||
if (status != NTLSTATUS_SUCCESS || !address) { gLastError = 127; return NULL; }
|
||||
return (void*)address;
|
||||
@@ -1497,7 +1506,7 @@ __declspec(dllexport) void* GetProcAddress(HANDLE hModule, const char* lpProcNam
|
||||
__declspec(dllexport) BOOL FreeLibrary(HANDLE hLibModule) {
|
||||
if (!hLibModule || hLibModule == WIN32_HMODULE_WIN32 || hLibModule == WIN32_HMODULE_EXE)
|
||||
return TRUE;
|
||||
uint32_t status = NtlUnloadModule((NTL_MODULE_HANDLE)(uintptr_t)hLibModule);
|
||||
KSTATUS status = NtlUnloadModule((NTL_MODULE_HANDLE)(uintptr_t)hLibModule);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
gLastError = 126;
|
||||
return FALSE;
|
||||
@@ -1535,7 +1544,7 @@ __declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitC
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint32_t s = SysKillProcess(HANDLE_TO_KH(hProcess), (int32_t)uExitCode);
|
||||
KSTATUS s = SysKillProcess(HANDLE_TO_KH(hProcess), (int32_t)uExitCode);
|
||||
if (s != 0) {
|
||||
gLastError = (s == NTLSTATUS_INVALID_HANDLE) ? 6 : 5;
|
||||
return FALSE;
|
||||
@@ -1636,7 +1645,7 @@ __declspec(dllexport) HANDLE CreateThread(void* lpThreadAttributes,
|
||||
&kh,
|
||||
&tid
|
||||
};
|
||||
uint32_t status = SysCreateThread(&req);
|
||||
KSTATUS status = SysCreateThread(&req);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
free(context);
|
||||
gLastError = status == NTLSTATUS_NO_MEMORY ? 8 : 11;
|
||||
@@ -1676,7 +1685,7 @@ __declspec(dllexport) DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMillisec
|
||||
uint64_t timeout = dwMilliseconds == INFINITE
|
||||
? SYS_WAIT_TIMEOUT_INFINITE
|
||||
: (uint64_t)dwMilliseconds;
|
||||
uint32_t s = SysWaitSingle(HANDLE_TO_KH(hHandle), SYS_WAIT_FLAG_NONE, timeout);
|
||||
KSTATUS s = SysWaitSingle(HANDLE_TO_KH(hHandle), SYS_WAIT_FLAG_NONE, timeout);
|
||||
if (s == NTLSTATUS_SUCCESS) return WAIT_OBJECT_0;
|
||||
if (s == NTLSTATUS_ABANDONED) return 0x00000080UL;
|
||||
if (s == NTLSTATUS_TIMEOUT) return WAIT_TIMEOUT;
|
||||
@@ -1697,7 +1706,7 @@ __declspec(dllexport) HANDLE CreateEventA(void* lpEventAttributes,
|
||||
}
|
||||
|
||||
uint32_t handle = 0;
|
||||
uint32_t status = SysCreateEvent(bManualReset ? 1u : 0u,
|
||||
KSTATUS status = SysCreateEvent(bManualReset ? 1u : 0u,
|
||||
bInitialState ? 1u : 0u,
|
||||
&handle);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
@@ -1722,7 +1731,7 @@ __declspec(dllexport) HANDLE CreateEventW(void* lpEventAttributes,
|
||||
// Signals one native event.
|
||||
__declspec(dllexport) BOOL SetEvent(HANDLE hEvent) {
|
||||
if (!IS_VALID_KERNEL_HANDLE(hEvent)) { gLastError = 6; return FALSE; }
|
||||
uint32_t status = SysSignalEvent(HANDLE_TO_KH(hEvent));
|
||||
KSTATUS status = SysSignalEvent(HANDLE_TO_KH(hEvent));
|
||||
if (status != NTLSTATUS_SUCCESS) { gLastError = 6; return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1730,7 +1739,7 @@ __declspec(dllexport) BOOL SetEvent(HANDLE hEvent) {
|
||||
// Clears one native event.
|
||||
__declspec(dllexport) BOOL ResetEvent(HANDLE hEvent) {
|
||||
if (!IS_VALID_KERNEL_HANDLE(hEvent)) { gLastError = 6; return FALSE; }
|
||||
uint32_t status = SysClearEvent(HANDLE_TO_KH(hEvent));
|
||||
KSTATUS status = SysClearEvent(HANDLE_TO_KH(hEvent));
|
||||
if (status != NTLSTATUS_SUCCESS) { gLastError = 6; return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1807,7 +1816,7 @@ __declspec(dllexport) BOOL CreateProcessA(
|
||||
(targetPath[2] == '\\' || targetPath[2] == '/'));
|
||||
if (relativeImage) {
|
||||
TranslatePath(targetPath, translatedPath);
|
||||
uint32_t openStatus = K32OpenFileNative(translatedPath,
|
||||
KSTATUS openStatus = K32OpenFileNative(translatedPath,
|
||||
SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY,
|
||||
SYS_FILE_OPEN_EXISTING,
|
||||
&imageFile);
|
||||
@@ -1853,7 +1862,7 @@ __declspec(dllexport) BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode
|
||||
uint32_t kh = HANDLE_TO_KH(hProcess);
|
||||
if (!kh) { gLastError = 6; return FALSE; }
|
||||
int32_t code = 0;
|
||||
uint32_t s = SysGetProcessExitCode(kh, &code);
|
||||
KSTATUS s = SysGetProcessExitCode(kh, &code);
|
||||
if (s != 0) { gLastError = 6; return FALSE; }
|
||||
*lpExitCode = (DWORD)code;
|
||||
return TRUE;
|
||||
@@ -1867,7 +1876,7 @@ __declspec(dllexport) DWORD ResumeThread(HANDLE hThread) {
|
||||
}
|
||||
|
||||
uint32_t previousSuspendCount = 0;
|
||||
uint32_t status = SysResumeThread(HANDLE_TO_KH(hThread),
|
||||
KSTATUS status = SysResumeThread(HANDLE_TO_KH(hThread),
|
||||
&previousSuspendCount);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
gLastError = status == NTLSTATUS_ACCESS_DENIED ? 5 : 6;
|
||||
@@ -1922,7 +1931,7 @@ static BOOL K32IsConsoleOutputHandle(HANDLE h) {
|
||||
}
|
||||
|
||||
// Implements the k32 Set Console Last Error operation.
|
||||
static void K32SetConsoleLastError(uint32_t status) {
|
||||
static void K32SetConsoleLastError(KSTATUS status) {
|
||||
switch (status) {
|
||||
case NTLSTATUS_SUCCESS:
|
||||
gLastError = 0;
|
||||
@@ -2011,7 +2020,7 @@ __declspec(dllexport) BOOL GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
|
||||
}
|
||||
|
||||
NTL_CONSOLE_INFO info;
|
||||
uint32_t s = NtlConsoleQueryInfo(SYS_HANDLE_INVALID, &info);
|
||||
KSTATUS s = NtlConsoleQueryInfo(SYS_HANDLE_INVALID, &info);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
K32SetConsoleLastError(s);
|
||||
return FALSE;
|
||||
@@ -2042,7 +2051,7 @@ __declspec(dllexport) BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint32_t s = NtlConsoleSetCursor(SYS_HANDLE_INVALID, (int)dwCursorPosition.X, (int)dwCursorPosition.Y);
|
||||
KSTATUS s = NtlConsoleSetCursor(SYS_HANDLE_INVALID, (int)dwCursorPosition.X, (int)dwCursorPosition.Y);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
K32SetConsoleLastError(s);
|
||||
return FALSE;
|
||||
@@ -2068,7 +2077,7 @@ __declspec(dllexport) BOOL FillConsoleOutputCharacterA(HANDLE hConsoleOutput,
|
||||
return TRUE;
|
||||
|
||||
size_t written = 0;
|
||||
uint32_t s = NtlConsoleFillCharacter(SYS_HANDLE_INVALID, cCharacter,
|
||||
KSTATUS s = NtlConsoleFillCharacter(SYS_HANDLE_INVALID, cCharacter,
|
||||
(int)dwWriteCoord.X, (int)dwWriteCoord.Y,
|
||||
(size_t)nLength, &written);
|
||||
if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = (DWORD)written;
|
||||
@@ -2097,7 +2106,7 @@ __declspec(dllexport) BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput,
|
||||
return TRUE;
|
||||
|
||||
size_t written = 0;
|
||||
uint32_t s = NtlConsoleFillAttribute(SYS_HANDLE_INVALID, wAttribute,
|
||||
KSTATUS s = NtlConsoleFillAttribute(SYS_HANDLE_INVALID, wAttribute,
|
||||
(int)dwWriteCoord.X, (int)dwWriteCoord.Y,
|
||||
(size_t)nLength, &written);
|
||||
if (lpNumberOfAttrsWritten) *lpNumberOfAttrsWritten = (DWORD)written;
|
||||
@@ -2123,22 +2132,22 @@ typedef struct {
|
||||
|
||||
// Minimal wildcard match: supports '*' (any sequence) and '?' (any char).
|
||||
// Case-insensitive to match FAT32/Windows behaviour.
|
||||
static int WildMatch(const char* pat, const char* name) {
|
||||
static bool WildMatch(const char* pat, const char* name) {
|
||||
while (*pat && *name) {
|
||||
if (*pat == '*') {
|
||||
// Skip consecutive stars.
|
||||
while (*pat == '*') pat++;
|
||||
if (!*pat) return 1; // trailing * matches everything
|
||||
if (!*pat) return true; // trailing * matches everything
|
||||
// Try matching the rest of the pattern at every position.
|
||||
while (*name) {
|
||||
if (WildMatch(pat, name)) return 1;
|
||||
if (WildMatch(pat, name)) return true;
|
||||
name++;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
char p = (*pat >= 'A' && *pat <= 'Z') ? *pat + 32 : *pat;
|
||||
char n = (*name >= 'A' && *name <= 'Z') ? *name + 32 : *name;
|
||||
if (*pat != '?' && p != n) return 0;
|
||||
if (*pat != '?' && p != n) return false;
|
||||
pat++; name++;
|
||||
}
|
||||
// Consume trailing stars in the pattern.
|
||||
@@ -2198,7 +2207,7 @@ static void SplitFindPath(const char* searchPath,
|
||||
#define FILE_ATTRIBUTE_NORMAL 0x00000080UL
|
||||
|
||||
// Implements the k32 Dir Is Leap Year operation.
|
||||
static int K32DirIsLeapYear(unsigned int year) {
|
||||
static bool K32DirIsLeapYear(unsigned int year) {
|
||||
return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u);
|
||||
}
|
||||
|
||||
@@ -2299,7 +2308,7 @@ __declspec(dllexport) HANDLE FindFirstFileA(const char* lpFileName,
|
||||
// Read the first entry that matches the pattern.
|
||||
KDIR_ENTRY ke;
|
||||
while (true) {
|
||||
uint32_t rs = SysReadDir(kh, &ke);
|
||||
KSTATUS rs = SysReadDir(kh, &ke);
|
||||
if (rs != 0) {
|
||||
// Directory exhausted or error.
|
||||
SysCloseHandle(kh);
|
||||
@@ -2325,7 +2334,7 @@ __declspec(dllexport) BOOL FindNextFileA(HANDLE hFindFile,
|
||||
KDIR_ENTRY ke;
|
||||
|
||||
while (true) {
|
||||
uint32_t rs = SysReadDir(fh->kh, &ke);
|
||||
KSTATUS rs = SysReadDir(fh->kh, &ke);
|
||||
if (rs != 0) {
|
||||
gLastError = 18; // ERROR_NO_MORE_FILES
|
||||
return FALSE;
|
||||
@@ -2416,7 +2425,7 @@ __declspec(dllexport) HANDLE CreateMutexA(void* lpMutexAttributes, BOOL bInitial
|
||||
gLastError = 8;
|
||||
return NULL;
|
||||
}
|
||||
uint32_t status = SysCreateMutex(&mutex->NativeHandle);
|
||||
KSTATUS status = SysCreateMutex(&mutex->NativeHandle);
|
||||
if (status != NTLSTATUS_SUCCESS || !mutex->NativeHandle) {
|
||||
free(mutex);
|
||||
gLastError = status == NTLSTATUS_NO_MEMORY ? 8 : 1;
|
||||
@@ -2473,7 +2482,7 @@ __declspec(dllexport) BOOL ReleaseMutex(HANDLE hMutex) {
|
||||
mutex->OwnerTid = 0;
|
||||
K32MutexStateUnlock(mutex);
|
||||
|
||||
uint32_t status = SysReleaseMutex(mutex->NativeHandle);
|
||||
KSTATUS status = SysReleaseMutex(mutex->NativeHandle);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
K32MutexStateLock(mutex);
|
||||
mutex->OwnerTid = tid;
|
||||
@@ -2492,7 +2501,7 @@ __declspec(dllexport) HANDLE CreateSemaphoreA(void* lpSemaphoreAttributes,
|
||||
const char* lpName) {
|
||||
(void)lpSemaphoreAttributes; (void)lpName;
|
||||
uint32_t kh = 0;
|
||||
uint32_t s = SysCreateSem((int32_t)lInitialCount, (int32_t)lMaximumCount, &kh);
|
||||
KSTATUS s = SysCreateSem((int32_t)lInitialCount, (int32_t)lMaximumCount, &kh);
|
||||
if (s != 0 || !kh) { gLastError = 8; return NULL; }
|
||||
return KH_TO_HANDLE(kh);
|
||||
}
|
||||
@@ -2502,7 +2511,7 @@ __declspec(dllexport) BOOL ReleaseSemaphore(HANDLE hSemaphore, long lReleaseCoun
|
||||
if (!IS_VALID_KERNEL_HANDLE(hSemaphore) || lReleaseCount < 0) { gLastError = 6; return FALSE; }
|
||||
if (lpPreviousCount) *lpPreviousCount = 0;
|
||||
for (long i = 0; i < lReleaseCount; ++i) {
|
||||
uint32_t s = SysSignalSem(HANDLE_TO_KH(hSemaphore));
|
||||
KSTATUS s = SysSignalSem(HANDLE_TO_KH(hSemaphore));
|
||||
if (s != 0) { gLastError = 6; return FALSE; }
|
||||
}
|
||||
return TRUE;
|
||||
@@ -2515,7 +2524,7 @@ __declspec(dllexport) BOOL ReleaseSemaphore(HANDLE hSemaphore, long lReleaseCoun
|
||||
// races as soon as CreateThread started working.
|
||||
typedef struct K32_CONDITION_WAITER K32_CONDITION_WAITER;
|
||||
typedef struct K32_CONDITION_STATE {
|
||||
volatile long Lock;
|
||||
int32_t Lock;
|
||||
K32_CONDITION_WAITER* Head;
|
||||
K32_CONDITION_WAITER* Tail;
|
||||
} K32_CONDITION_STATE;
|
||||
@@ -2527,14 +2536,6 @@ struct K32_CONDITION_WAITER {
|
||||
BOOL Queued;
|
||||
};
|
||||
|
||||
#define K32_CS_LOCK 0
|
||||
#define K32_CS_OWNER 1
|
||||
#define K32_CS_RECURSION 2
|
||||
|
||||
static volatile long* K32CsLockWord(CRITICAL_SECTION* cs) {
|
||||
return (volatile long*)&cs->_opaque[K32_CS_LOCK];
|
||||
}
|
||||
|
||||
static DWORD K32CurrentTidOrOne(void) {
|
||||
DWORD tid = (DWORD)SysGetCurrentTid();
|
||||
return tid ? tid : 1;
|
||||
@@ -2557,51 +2558,51 @@ __declspec(dllexport) void DeleteCriticalSection(CRITICAL_SECTION* lpCS) { (voi
|
||||
__declspec(dllexport) void EnterCriticalSection(CRITICAL_SECTION* lpCS) {
|
||||
if (!lpCS) return;
|
||||
DWORD tid = K32CurrentTidOrOne();
|
||||
if ((DWORD)lpCS->_opaque[K32_CS_OWNER] == tid) {
|
||||
lpCS->_opaque[K32_CS_RECURSION]++;
|
||||
if ((DWORD)lpCS->Owner == tid) {
|
||||
lpCS->Recursion++;
|
||||
return;
|
||||
}
|
||||
uint32_t spins = 0;
|
||||
while (_InterlockedCompareExchange(K32CsLockWord(lpCS), 1, 0) != 0) {
|
||||
while (NtlAtomicCompareExchange32(&lpCS->Lock, 1, 0) != 0) {
|
||||
_mm_pause();
|
||||
if ((++spins & 0xFFFu) == 0)
|
||||
(void)SysYield();
|
||||
}
|
||||
lpCS->_opaque[K32_CS_OWNER] = tid;
|
||||
lpCS->_opaque[K32_CS_RECURSION] = 1;
|
||||
lpCS->Owner = tid;
|
||||
lpCS->Recursion = 1;
|
||||
}
|
||||
// Implements the leave Critical Section operation.
|
||||
__declspec(dllexport) void LeaveCriticalSection(CRITICAL_SECTION* lpCS) {
|
||||
if (!lpCS) return;
|
||||
DWORD tid = K32CurrentTidOrOne();
|
||||
if ((DWORD)lpCS->_opaque[K32_CS_OWNER] != tid || lpCS->_opaque[K32_CS_RECURSION] == 0)
|
||||
if ((DWORD)lpCS->Owner != tid || lpCS->Recursion == 0)
|
||||
return;
|
||||
lpCS->_opaque[K32_CS_RECURSION]--;
|
||||
if (lpCS->_opaque[K32_CS_RECURSION] == 0) {
|
||||
lpCS->_opaque[K32_CS_OWNER] = 0;
|
||||
lpCS->Recursion--;
|
||||
if (lpCS->Recursion == 0) {
|
||||
lpCS->Owner = 0;
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(K32CsLockWord(lpCS), 0);
|
||||
NtlAtomicExchange32(&lpCS->Lock, 0);
|
||||
}
|
||||
}
|
||||
// Implements the try Enter Critical Section operation.
|
||||
__declspec(dllexport) BOOL TryEnterCriticalSection(CRITICAL_SECTION* lpCS) {
|
||||
if (!lpCS) return FALSE;
|
||||
DWORD tid = K32CurrentTidOrOne();
|
||||
if ((DWORD)lpCS->_opaque[K32_CS_OWNER] == tid) {
|
||||
lpCS->_opaque[K32_CS_RECURSION]++;
|
||||
if ((DWORD)lpCS->Owner == tid) {
|
||||
lpCS->Recursion++;
|
||||
return TRUE;
|
||||
}
|
||||
if (_InterlockedCompareExchange(K32CsLockWord(lpCS), 1, 0) != 0)
|
||||
if (NtlAtomicCompareExchange32(&lpCS->Lock, 1, 0) != 0)
|
||||
return FALSE;
|
||||
lpCS->_opaque[K32_CS_OWNER] = tid;
|
||||
lpCS->_opaque[K32_CS_RECURSION] = 1;
|
||||
lpCS->Owner = tid;
|
||||
lpCS->Recursion = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Acquires one condition-variable queue lock.
|
||||
static void K32ConditionLock(K32_CONDITION_STATE* state) {
|
||||
uint32_t spins = 0;
|
||||
while (_InterlockedCompareExchange(&state->Lock, 1, 0) != 0) {
|
||||
while (NtlAtomicCompareExchange32(&state->Lock, 1, 0) != 0) {
|
||||
_mm_pause();
|
||||
if ((++spins & 0xFFFu) == 0)
|
||||
(void)SysYield();
|
||||
@@ -2611,7 +2612,7 @@ static void K32ConditionLock(K32_CONDITION_STATE* state) {
|
||||
// Releases one condition-variable queue lock.
|
||||
static void K32ConditionUnlock(K32_CONDITION_STATE* state) {
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(&state->Lock, 0);
|
||||
NtlAtomicExchange32(&state->Lock, 0);
|
||||
}
|
||||
|
||||
// Returns the lazily allocated process-local condition-variable state.
|
||||
@@ -2627,7 +2628,7 @@ static K32_CONDITION_STATE* K32ConditionState(CONDITION_VARIABLE* cv, BOOL creat
|
||||
if (!allocated)
|
||||
return NULL;
|
||||
|
||||
void* previous = _InterlockedCompareExchangePointer((void* volatile*)&cv->_ptr,
|
||||
void* previous = NtlAtomicCompareExchangePointer(&cv->_ptr,
|
||||
allocated,
|
||||
NULL);
|
||||
if (previous) {
|
||||
@@ -2676,8 +2677,8 @@ __declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv,
|
||||
}
|
||||
|
||||
DWORD tid = K32CurrentTidOrOne();
|
||||
uintptr_t recursion = cs->_opaque[K32_CS_RECURSION];
|
||||
if ((DWORD)cs->_opaque[K32_CS_OWNER] != tid || recursion == 0) {
|
||||
uintptr_t recursion = cs->Recursion;
|
||||
if ((DWORD)cs->Owner != tid || recursion == 0) {
|
||||
gLastError = 87;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2717,10 +2718,10 @@ __declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv,
|
||||
|
||||
// The waiter is visible before the lock is released, so a wake that races
|
||||
// this transition is retained by the private auto-reset event.
|
||||
cs->_opaque[K32_CS_RECURSION] = 0;
|
||||
cs->_opaque[K32_CS_OWNER] = 0;
|
||||
cs->Recursion = 0;
|
||||
cs->Owner = 0;
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(K32CsLockWord(cs), 0);
|
||||
NtlAtomicExchange32(&cs->Lock, 0);
|
||||
|
||||
uint64_t timeout = dwMilliseconds == INFINITE
|
||||
? SYS_WAIT_TIMEOUT_INFINITE
|
||||
@@ -2733,7 +2734,7 @@ __declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv,
|
||||
K32ConditionUnlock(state);
|
||||
|
||||
EnterCriticalSection(cs);
|
||||
cs->_opaque[K32_CS_RECURSION] = recursion;
|
||||
cs->Recursion = recursion;
|
||||
(void)SysCloseHandle(event);
|
||||
free(waiter);
|
||||
|
||||
@@ -2783,7 +2784,7 @@ typedef union {
|
||||
long long QuadPart;
|
||||
} LARGE_INTEGER;
|
||||
|
||||
static volatile long long gTscFreq = 0;
|
||||
static int64_t gTscFreq;
|
||||
|
||||
// Attempt to read TSC frequency from CPUID leaf 0x15 (Modern Intel/AMD).
|
||||
static long long TscFreqFromCpuid(void) {
|
||||
@@ -2797,7 +2798,7 @@ static long long TscFreqFromCpuid(void) {
|
||||
unsigned crystal_hz = (unsigned)info[2];
|
||||
|
||||
if (!denom || !numer || !crystal_hz) return 0;
|
||||
return (long long)crystal_hz * numer / denom;
|
||||
return (int64_t)crystal_hz * numer / denom;
|
||||
}
|
||||
|
||||
// Calibrates TSC against the native monotonic tick source.
|
||||
@@ -2822,18 +2823,21 @@ static long long TscFreqCalibrate(void) {
|
||||
uint64_t delta_us = SysTicksToMicroseconds(t1 - t0, frequency);
|
||||
if (!delta_us) return 0;
|
||||
|
||||
return (long long)(delta_tsc * 1000000ULL / delta_us);
|
||||
return (int64_t)(delta_tsc * 1000000ULL / delta_us);
|
||||
}
|
||||
|
||||
// Implements the tsc Freq Get operation.
|
||||
static long long TscFreqGet(void) {
|
||||
if (gTscFreq) return gTscFreq;
|
||||
int64_t cached = NtlAtomicLoad64(&gTscFreq);
|
||||
if (cached)
|
||||
return cached;
|
||||
|
||||
long long f = TscFreqFromCpuid();
|
||||
if (!f) f = TscFreqCalibrate();
|
||||
int64_t frequency = TscFreqFromCpuid();
|
||||
if (!frequency)
|
||||
frequency = TscFreqCalibrate();
|
||||
|
||||
gTscFreq = f;
|
||||
return f;
|
||||
int64_t previous = NtlAtomicCompareExchange64(&gTscFreq, frequency, 0);
|
||||
return previous ? previous : frequency;
|
||||
}
|
||||
|
||||
// Returns performance Frequency.
|
||||
@@ -2847,7 +2851,7 @@ __declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceC
|
||||
// Ensure calibration happens before the first read.
|
||||
TscFreqGet();
|
||||
if (lpPerformanceCount)
|
||||
lpPerformanceCount->QuadPart = (long long)__rdtsc();
|
||||
lpPerformanceCount->QuadPart = (int64_t)__rdtsc();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3185,8 +3189,8 @@ typedef struct _RTL_EXCEPTION_FRAME {
|
||||
} RTL_EXCEPTION_FRAME;
|
||||
|
||||
typedef struct WIN_VECTORED_HANDLER_ENTRY {
|
||||
uint32_t Active;
|
||||
uint32_t IsContinue;
|
||||
bool Active;
|
||||
bool IsContinue;
|
||||
uint32_t Previous;
|
||||
uint32_t Next;
|
||||
PVECTORED_EXCEPTION_HANDLER Handler;
|
||||
@@ -3201,7 +3205,7 @@ typedef struct WIN_SEH_FRAME_SNAPSHOT {
|
||||
void* UserContext;
|
||||
} WIN_SEH_FRAME_SNAPSHOT;
|
||||
|
||||
static volatile long gWinVectoredLock;
|
||||
static int32_t gWinVectoredLock;
|
||||
static uint32_t gWinVectoredExceptionHead = UINT32_MAX;
|
||||
static uint32_t gWinVectoredExceptionTail = UINT32_MAX;
|
||||
static uint32_t gWinVectoredContinueHead = UINT32_MAX;
|
||||
@@ -3211,7 +3215,7 @@ static void* gWinExceptionNativeHandle;
|
||||
|
||||
// Acquires the Win32 vectored-handler list lock.
|
||||
static void WinpVectoredLock(void) {
|
||||
while (_InterlockedCompareExchange(&gWinVectoredLock, 1, 0) != 0)
|
||||
while (NtlAtomicCompareExchange32(&gWinVectoredLock, 1, 0) != 0)
|
||||
_mm_pause();
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
@@ -3219,7 +3223,7 @@ static void WinpVectoredLock(void) {
|
||||
// Releases the Win32 vectored-handler list lock.
|
||||
static void WinpVectoredUnlock(void) {
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(&gWinVectoredLock, 0);
|
||||
NtlAtomicExchange32(&gWinVectoredLock, 0);
|
||||
}
|
||||
|
||||
// Returns the list head slot for one vectored-handler kind.
|
||||
@@ -3440,7 +3444,7 @@ static int WinpRunSehFrames(EXCEPTION_POINTERS* pointers, SYS_USER_CONTEXT* nati
|
||||
}
|
||||
|
||||
// Bridges the native exception runtime into Win32 exception policy.
|
||||
static int WinpExceptionNativeDispatch(SYS_EXCEPTION_RECORD* record, SYS_USER_CONTEXT* context, void* userContext) {
|
||||
static uint32_t WinpExceptionNativeDispatch(SYS_EXCEPTION_RECORD* record, SYS_USER_CONTEXT* context, void* userContext) {
|
||||
(void)userContext;
|
||||
|
||||
EXCEPTION_RECORD winRecord;
|
||||
@@ -3654,7 +3658,7 @@ __declspec(dllexport) void RaiseException(DWORD dwExceptionCode, DWORD dwExcepti
|
||||
request.ParameterCount = count;
|
||||
request.Parameters = count ? arguments : NULL;
|
||||
|
||||
uint32_t status = SysRaiseException(&request);
|
||||
KSTATUS status = SysRaiseException(&request);
|
||||
if (status != NTLSTATUS_SUCCESS)
|
||||
SysExitProcess((int32_t)status);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// WinMM waveform output over the native render-stream syscall ABI.
|
||||
|
||||
#include <ntlite/atomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -158,15 +160,15 @@ typedef struct WINMM_WAVE_BUFFER {
|
||||
uint32_t FrameCount;
|
||||
uint32_t SubmittedFrames;
|
||||
uint64_t PresentedTarget;
|
||||
uint8_t FullySubmitted;
|
||||
bool FullySubmitted;
|
||||
uint64_t Sequence;
|
||||
} WINMM_WAVE_BUFFER;
|
||||
|
||||
typedef struct WINMM_WAVEOUT {
|
||||
struct WINMM_WAVEOUT* RegistryNext;
|
||||
uint32_t Magic;
|
||||
volatile long Lock;
|
||||
volatile long ApiUsers;
|
||||
int32_t Lock;
|
||||
int32_t ApiUsers;
|
||||
uint32_t NativeStream;
|
||||
uint32_t WakeEvent;
|
||||
uint32_t CommandEvent;
|
||||
@@ -180,10 +182,10 @@ typedef struct WINMM_WAVEOUT {
|
||||
uint32_t CallbackMode;
|
||||
uint32_t DeviceId;
|
||||
uint32_t Volume;
|
||||
uint32_t Closing;
|
||||
uint32_t UserPaused;
|
||||
uint32_t AutoPaused;
|
||||
uint32_t Started;
|
||||
bool Closing;
|
||||
bool UserPaused;
|
||||
bool AutoPaused;
|
||||
bool Started;
|
||||
uint32_t TerminalError;
|
||||
WINMM_WAVE_COMMAND Command;
|
||||
MMRESULT CommandResult;
|
||||
@@ -198,7 +200,7 @@ typedef struct WINMM_WAVEOUT {
|
||||
} WINMM_WAVEOUT;
|
||||
|
||||
static WINMM_WAVEOUT* gWaveOutRegistry;
|
||||
static volatile long gWaveOutRegistryLock;
|
||||
static int32_t gWaveOutRegistryLock;
|
||||
|
||||
|
||||
typedef struct WINMM_DEBUG_LINE {
|
||||
@@ -230,12 +232,12 @@ static void WinmmDebugU64(WINMM_DEBUG_LINE* line, uint64_t value) {
|
||||
static void WinmmDebugHex(WINMM_DEBUG_LINE* line, uint64_t value) {
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
WinmmDebugText(line, "0x");
|
||||
int started = 0;
|
||||
bool started = false;
|
||||
for (int shift = 60; shift >= 0; shift -= 4) {
|
||||
uint8_t digit = (uint8_t)((value >> shift) & 0xFu);
|
||||
if (!started && digit == 0 && shift)
|
||||
continue;
|
||||
started = 1;
|
||||
started = true;
|
||||
if (line->Length + 1 < sizeof(line->Buffer))
|
||||
line->Buffer[line->Length++] = digits[digit];
|
||||
}
|
||||
@@ -295,14 +297,14 @@ static void WinmmDebugResult(const char* operation,
|
||||
}
|
||||
|
||||
// Acquires one short user-mode spin lock without entering the kernel.
|
||||
static void WinmmLock(volatile long* lock) {
|
||||
while (_InterlockedCompareExchange(lock, 1, 0) != 0)
|
||||
static void WinmmLock(int32_t* lock) {
|
||||
while (NtlAtomicCompareExchange32(lock, 1, 0) != 0)
|
||||
(void)SysYield();
|
||||
}
|
||||
|
||||
// Releases one short user-mode spin lock.
|
||||
static void WinmmUnlock(volatile long* lock) {
|
||||
_InterlockedExchange(lock, 0);
|
||||
static void WinmmUnlock(int32_t* lock) {
|
||||
NtlAtomicExchange32(lock, 0);
|
||||
}
|
||||
|
||||
// Maps one native status to the closest waveform-open result.
|
||||
@@ -321,7 +323,7 @@ static MMRESULT WinmmMapNativeStatus(KSTATUS status) {
|
||||
}
|
||||
|
||||
// Returns whether one source rate is accepted by the native stream ABI.
|
||||
static int WinmmRateIsSupported(uint32_t sampleRate) {
|
||||
static bool WinmmRateIsSupported(uint32_t sampleRate) {
|
||||
return sampleRate == 11025u || sampleRate == 22050u ||
|
||||
sampleRate == 44100u || sampleRate == 48000u;
|
||||
}
|
||||
@@ -439,7 +441,7 @@ static WINMM_WAVEOUT* WinmmReferenceWaveOut(HWAVEOUT handle) {
|
||||
current;
|
||||
current = current->RegistryNext) {
|
||||
if ((HWAVEOUT)current == handle && current->Magic == WINMM_WAVEOUT_MAGIC) {
|
||||
_InterlockedIncrement(¤t->ApiUsers);
|
||||
NtlAtomicIncrement32(¤t->ApiUsers);
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
@@ -451,19 +453,19 @@ static WINMM_WAVEOUT* WinmmReferenceWaveOut(HWAVEOUT handle) {
|
||||
// Releases one API-use reference acquired through the registry.
|
||||
static void WinmmReleaseWaveOut(WINMM_WAVEOUT* waveOut) {
|
||||
if (waveOut)
|
||||
_InterlockedDecrement(&waveOut->ApiUsers);
|
||||
NtlAtomicDecrement32(&waveOut->ApiUsers);
|
||||
}
|
||||
|
||||
// Removes one waveform handle so no new API references can be acquired.
|
||||
static int WinmmRemoveWaveOut(WINMM_WAVEOUT* waveOut) {
|
||||
int removed = 0;
|
||||
static bool WinmmRemoveWaveOut(WINMM_WAVEOUT* waveOut) {
|
||||
bool removed = false;
|
||||
WinmmLock(&gWaveOutRegistryLock);
|
||||
WINMM_WAVEOUT** link = &gWaveOutRegistry;
|
||||
while (*link) {
|
||||
if (*link == waveOut) {
|
||||
*link = waveOut->RegistryNext;
|
||||
waveOut->RegistryNext = NULL;
|
||||
removed = 1;
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
link = &(*link)->RegistryNext;
|
||||
@@ -713,7 +715,7 @@ static KSTATUS WinmmFeedNativeStream(WINMM_WAVEOUT* waveOut,
|
||||
}
|
||||
|
||||
// Determines whether any queued buffer still needs native-ring submission.
|
||||
static int WinmmHasUnsubmittedBuffer(WINMM_WAVEOUT* waveOut) {
|
||||
static bool WinmmHasUnsubmittedBuffer(WINMM_WAVEOUT* waveOut) {
|
||||
return WinmmFindSubmitNode(waveOut) != NULL;
|
||||
}
|
||||
|
||||
@@ -751,7 +753,7 @@ static void WinmmStopEmptyStream(WINMM_WAVEOUT* waveOut) {
|
||||
// Arms native progress conditions and waits for either stream progress or new work.
|
||||
static KSTATUS WinmmWaitForWork(WINMM_WAVEOUT* waveOut,
|
||||
const SYS_AUDIO_STREAM_INFO* info,
|
||||
int hasUnsubmitted) {
|
||||
bool hasUnsubmitted) {
|
||||
SYS_AUDIO_ARM_WAIT_REQUEST arm;
|
||||
memset(&arm, 0, sizeof(arm));
|
||||
arm.Size = sizeof(arm);
|
||||
@@ -877,7 +879,7 @@ static void WinmmWaveWorker(uintptr_t argument) {
|
||||
WinmmFailStream(waveOut, WinmmMapNativeStatus(status));
|
||||
continue;
|
||||
}
|
||||
int hasUnsubmitted = WinmmHasUnsubmittedBuffer(waveOut);
|
||||
bool hasUnsubmitted = WinmmHasUnsubmittedBuffer(waveOut);
|
||||
if (!hasUnsubmitted && waveOut->Started && !waveOut->UserPaused &&
|
||||
!waveOut->AutoPaused && info.FramesConsumed >= waveOut->NativeSubmitted) {
|
||||
status = SysAudioPause(waveOut->NativeStream);
|
||||
@@ -1088,7 +1090,7 @@ __declspec(dllexport) MMRESULT waveOutClose(HWAVEOUT handle) {
|
||||
}
|
||||
|
||||
WinmmLock(&waveOut->Lock);
|
||||
int busy = waveOut->QueueHead != NULL || waveOut->Command != WinmmWaveCommandNone;
|
||||
bool busy = waveOut->QueueHead != NULL || waveOut->Command != WinmmWaveCommandNone;
|
||||
WinmmUnlock(&waveOut->Lock);
|
||||
if (busy) {
|
||||
WinmmDebugResult("close still playing", waveOut, waveOut->HeadersQueued - waveOut->HeadersCompleted);
|
||||
@@ -1103,7 +1105,7 @@ __declspec(dllexport) MMRESULT waveOutClose(HWAVEOUT handle) {
|
||||
waveOut->Closing = 1;
|
||||
(void)SysSignalEvent(waveOut->WakeEvent);
|
||||
KSTATUS status = SysWait(waveOut->WorkerHandle, SYS_WAIT_FLAG_NONE);
|
||||
while (waveOut->ApiUsers > 1)
|
||||
while (NtlAtomicLoad32(&waveOut->ApiUsers) > 1)
|
||||
(void)SysYield();
|
||||
|
||||
waveOut->Magic = 0;
|
||||
|
||||
Reference in new issue
Block a user