diff --git a/Source/Windows/Common/CMakeLists.txt b/Source/Windows/Common/CMakeLists.txt index 9261ef507..ae5ac2de6 100644 --- a/Source/Windows/Common/CMakeLists.txt +++ b/Source/Windows/Common/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(CommonWindows STATIC CPUFeatures.cpp InvalidationTracker.cpp Logging.cpp) add_subdirectory(CRT) +add_subdirectory(WinAPI) target_link_libraries(CommonWindows FEXCore_Base) target_compile_options(CommonWindows PRIVATE -Wno-inconsistent-dllimport) target_include_directories(CommonWindows PRIVATE diff --git a/Source/Windows/Common/WinAPI/Alloc.cpp b/Source/Windows/Common/WinAPI/Alloc.cpp new file mode 100644 index 000000000..660f913a5 --- /dev/null +++ b/Source/Windows/Common/WinAPI/Alloc.cpp @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +#define NTDDI_VERSION 0x0A000005 +#define WINAPI +#define WINBASEAPI + +#include +#include +#include +#include +#include +#include +#include +#include "../Priv.h" + +DLLEXPORT_FUNC(void*, VirtualAlloc, (void* lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)) { + NTSTATUS Status = NtAllocateVirtualMemory(NtCurrentProcess(), &lpAddress, 0, &dwSize, flAllocationType, flProtect); + if (Status) { + SetLastError(RtlNtStatusToDosError(Status)); + return nullptr; + } + return lpAddress; +} + +DLLEXPORT_FUNC(SIZE_T, VirtualQuery, (LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)) { + SIZE_T WrittenSize; + NTSTATUS Status = + NtQueryVirtualMemory(NtCurrentProcess(), lpAddress, MemoryBasicInformation, reinterpret_cast(lpBuffer), dwLength, &WrittenSize); + if (Status) { + SetLastError(RtlNtStatusToDosError(Status)); + return 0; + } + return WrittenSize; +} + +DLLEXPORT_FUNC(WINBOOL, VirtualProtect, (void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)) { + return WinAPIReturn(NtProtectVirtualMemory(NtCurrentProcess(), &lpAddress, &dwSize, flNewProtect, lpflOldProtect)); +} + +DLLEXPORT_FUNC(void*, VirtualAlloc2, + (HANDLE Process, void* BaseAddress, SIZE_T Size, ULONG AllocationType, ULONG PageProtection, + MEM_EXTENDED_PARAMETER* ExtendedParameters, ULONG ParameterCount)) { + NTSTATUS Status = NtAllocateVirtualMemoryEx(Process ? Process : NtCurrentProcess(), &BaseAddress, &Size, AllocationType, PageProtection, + ExtendedParameters, ParameterCount); + if (Status) { + SetLastError(RtlNtStatusToDosError(Status)); + return nullptr; + } + return BaseAddress; +} + +DLLEXPORT_FUNC(WINBOOL, VirtualFree, (void* lpAddress, SIZE_T dwSize, DWORD dwFreeType)) { + return WinAPIReturn(NtFreeVirtualMemory(NtCurrentProcess(), &lpAddress, &dwSize, dwFreeType)); +} + +DLLEXPORT_FUNC(WINBOOL, FlushInstructionCache, (HANDLE hProcess, const void* lpBaseAddress, SIZE_T dwSize)) { + return WinAPIReturn(NtFlushInstructionCache(hProcess, const_cast(lpBaseAddress), dwSize)); +} + +DLLEXPORT_FUNC(DWORD, FlsAlloc, (PFLS_CALLBACK_FUNCTION lpCallback)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(void*, FlsGetValue, (DWORD dwFlsIndex)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, FlsSetValue, (DWORD dwFlsIndex, void* lpFlsData)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, FlsFree, (DWORD dwFlsIndex)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, TlsAlloc, ()) { + RtlAcquirePebLock(); + + // Cannot use expansion slots or FLS here, as they would be freed before FEX can cleanup. + DWORD Slot = RtlFindClearBitsAndSet(GetCurrentPEB()->TlsBitmap, 1, 1); + if (Slot != -1) { + GetCurrentTEB()->TlsSlots[Slot] = nullptr; + } + RtlReleasePebLock(); + return Slot; +} + +DLLEXPORT_FUNC(void*, TlsGetValue, (DWORD dwTlsIndex)) { + return GetCurrentTEB()->TlsSlots[dwTlsIndex]; +} + +DLLEXPORT_FUNC(WINBOOL, TlsSetValue, (DWORD dwTlsIndex, void* lpTlsValue)) { + GetCurrentTEB()->TlsSlots[dwTlsIndex] = lpTlsValue; + return true; +} + +DLLEXPORT_FUNC(WINBOOL, TlsFree, (DWORD dwTlsIndex)) { + RtlAcquirePebLock(); + + RtlClearBits(GetCurrentPEB()->TlsBitmap, dwTlsIndex, 1); + NTSTATUS Status = NtSetInformationThread(NtCurrentThread(), ThreadZeroTlsCell, &dwTlsIndex, sizeof(dwTlsIndex)); + RtlReleasePebLock(); + return WinAPIReturn(Status); +} diff --git a/Source/Windows/Common/WinAPI/CMakeLists.txt b/Source/Windows/Common/WinAPI/CMakeLists.txt new file mode 100644 index 000000000..3251318e4 --- /dev/null +++ b/Source/Windows/Common/WinAPI/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(CommonWindows PRIVATE Alloc.cpp Sync.cpp IO.cpp Misc.cpp) diff --git a/Source/Windows/Common/WinAPI/IO.cpp b/Source/Windows/Common/WinAPI/IO.cpp new file mode 100644 index 000000000..790b286ec --- /dev/null +++ b/Source/Windows/Common/WinAPI/IO.cpp @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: MIT +#define NTDDI_VERSION 0x0A000005 +#define WINAPI +#define WINBASEAPI + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../Priv.h" + +namespace { +ULONG CreateDispositionToNT(DWORD Disposition) { + switch (Disposition) { + case CREATE_ALWAYS: return FILE_OVERWRITE_IF; + case CREATE_NEW: return FILE_CREATE; + case TRUNCATE_EXISTING: return FILE_OVERWRITE; + case OPEN_ALWAYS: return FILE_OPEN_IF; + case OPEN_EXISTING: return FILE_OPEN; + default: UNIMPLEMENTED(); + } +} + +FILE_INFORMATION_CLASS FileInfoClassToNT(FILE_INFO_BY_HANDLE_CLASS InformationClass) { + switch (InformationClass) { + case FileBasicInfo: return FileBasicInformation; + case FileStandardInfo: return FileStandardInformation; + default: UNIMPLEMENTED(); + } +} +} // namespace + +DLLEXPORT_FUNC(HANDLE, CreateFileA, + (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)) { + + ScopedUnicodeString FileName {lpFileName}; + return CreateFileW(FileName->Buffer, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile); +} + +DLLEXPORT_FUNC(HANDLE, CreateFileW, + (LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)) { + UNICODE_STRING PathW; + RtlInitUnicodeString(&PathW, lpFileName); + + UNICODE_STRING NTPath; + if (!RtlDosPathNameToNtPathName_U(PathW.Buffer, &NTPath, nullptr, nullptr)) { + SetLastError(ERROR_PATH_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + OBJECT_ATTRIBUTES ObjAttributes; + InitializeObjectAttributes(&ObjAttributes, &NTPath, OBJ_CASE_INSENSITIVE, nullptr, nullptr); + + HANDLE Handle; + IO_STATUS_BLOCK IOSB; + NTSTATUS Status = NtCreateFile(&Handle, dwDesiredAccess | GENERIC_READ | SYNCHRONIZE, &ObjAttributes, &IOSB, nullptr, dwFlagsAndAttributes, + dwShareMode, CreateDispositionToNT(dwCreationDisposition), FILE_SYNCHRONOUS_IO_NONALERT, nullptr, 0); + return WinAPIReturn(Status) ? Handle : INVALID_HANDLE_VALUE; +} + +DLLEXPORT_FUNC(WINBOOL, WriteFile, + (HANDLE hFile, const void* lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)) { + IO_STATUS_BLOCK IOSB; + if (lpOverlapped) { + UNIMPLEMENTED(); + } + NTSTATUS Status = NtWriteFile(hFile, nullptr, nullptr, nullptr, &IOSB, lpBuffer, nNumberOfBytesToWrite, nullptr, nullptr); + if (lpNumberOfBytesWritten) { + *lpNumberOfBytesWritten = static_cast(IOSB.Information); + } + return WinAPIReturn(Status); +} + +DLLEXPORT_FUNC(HANDLE, GetStdHandle, (DWORD nStdHandle)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, WriteConsoleA, + (HANDLE hConsoleOutput, CONST void* lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, void* lpReserved)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, WriteConsoleW, + (HANDLE hConsoleOutput, CONST void* lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, void* lpReserved)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetFilePointerEx, (HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)) { + IO_STATUS_BLOCK IOSB; + FILE_POSITION_INFORMATION PositionInfo; + if (NTSTATUS Status = NtQueryInformationFile(hFile, &IOSB, &PositionInfo, sizeof(PositionInfo), FilePositionInformation); Status) { + return WinAPIReturn(Status); + } + FILE_END_OF_FILE_INFORMATION EOFInfo; + if (NTSTATUS Status = NtQueryInformationFile(hFile, &IOSB, &EOFInfo, sizeof(EOFInfo), FileEndOfFileInformation); Status) { + return WinAPIReturn(Status); + } + + switch (dwMoveMethod) { + case FILE_BEGIN: PositionInfo.CurrentByteOffset = liDistanceToMove; break; + case FILE_CURRENT: PositionInfo.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart; break; + case FILE_END: PositionInfo.CurrentByteOffset = EOFInfo.EndOfFile; break; + default: UNIMPLEMENTED(); + } + if (NTSTATUS Status = NtSetInformationFile(hFile, &IOSB, &PositionInfo, sizeof(PositionInfo), FilePositionInformation); Status) { + return WinAPIReturn(Status); + } + if (lpNewFilePointer) { + *lpNewFilePointer = PositionInfo.CurrentByteOffset; + } + return true; +} + +DLLEXPORT_FUNC(WINBOOL, ReadFile, + (HANDLE hFile, void* lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)) { + IO_STATUS_BLOCK IOSB; + if (lpOverlapped) { + UNIMPLEMENTED(); + } + NTSTATUS Status = NtReadFile(hFile, nullptr, nullptr, nullptr, &IOSB, lpBuffer, nNumberOfBytesToRead, nullptr, nullptr); + if (lpNumberOfBytesRead) { + *lpNumberOfBytesRead = static_cast(IOSB.Information); + } + return WinAPIReturn(Status); +} + +DLLEXPORT_FUNC(WINBOOL, FlushFileBuffers, (HANDLE hFile)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetFinalPathNameByHandleA, (HANDLE hFile, LPSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetFinalPathNameByHandleW, (HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, CreateHardLinkA, (LPCSTR lpFileName, LPCSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, CreateHardLinkW, (LPCWSTR lpFileName, LPCWSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, CreateDirectoryA, (LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, CreateDirectoryW, (LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, GetFileInformationByHandle, (HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)) { + FILE_BASIC_INFO BasicInfo; + if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &BasicInfo, sizeof(BasicInfo))) { + return false; + } + FILE_STANDARD_INFO StandardInfo; + if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &StandardInfo, sizeof(StandardInfo))) { + return false; + } + + *lpFileInformation = BY_HANDLE_FILE_INFORMATION { + .dwFileAttributes = BasicInfo.FileAttributes, + .ftCreationTime = {static_cast(BasicInfo.CreationTime.LowPart), static_cast(BasicInfo.CreationTime.HighPart)}, + .ftLastAccessTime = {static_cast(BasicInfo.LastAccessTime.LowPart), static_cast(BasicInfo.LastAccessTime.HighPart)}, + .ftLastWriteTime = {static_cast(BasicInfo.LastWriteTime.LowPart), static_cast(BasicInfo.LastWriteTime.HighPart)}, + .dwVolumeSerialNumber = 0, + .nFileSizeHigh = static_cast(StandardInfo.EndOfFile.HighPart), + .nFileSizeLow = static_cast(StandardInfo.EndOfFile.LowPart), + .nNumberOfLinks = StandardInfo.NumberOfLinks, + .nFileIndexHigh = 0, + .nFileIndexLow = 0}; + return true; +} + +DLLEXPORT_FUNC(WINBOOL, SetFileInformationByHandle, + (HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, void* lpFileInformation, DWORD dwBufferSize)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetEndOfFile, (HANDLE hFile)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetFileAttributesA, (LPCSTR lpFileName)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetFileAttributesW, (LPCWSTR lpFileName)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetFileAttributesA, (LPCSTR lpFileName, DWORD dwFileAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetFileAttributesW, (LPCWSTR lpFileName, DWORD dwFileAttributes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetFileTime, + (HANDLE hFile, CONST FILETIME* lpCreationTime, CONST FILETIME* lpLastAccessTime, CONST FILETIME* lpLastWriteTime)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, MoveFileExA, (LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, MoveFileExW, (LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, GetDiskFreeSpaceExA, + (LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, GetDiskFreeSpaceExW, + (LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetTempPathA, (DWORD nBufferLength, LPSTR lpBuffer)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetTempPathW, (DWORD nBufferLength, LPWSTR lpBuffer)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(BOOLEAN, CreateSymbolicLinkA, (LPCSTR lpSymlinkFileName, LPCSTR lpTargetFileName, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(BOOLEAN, CreateSymbolicLinkW, (LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, AreFileApisANSI, ()) { + return true; +} + +DLLEXPORT_FUNC(WINBOOL, FindNextFileA, (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, FindNextFileW, (HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, FindClose, (HANDLE hFindFile)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(HANDLE, FindFirstFileA, (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(HANDLE, FindFirstFileW, (LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, DeviceIoControl, + (HANDLE hDevice, DWORD dwIoControlCode, void* lpInBuffer, DWORD nInBufferSize, void* lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, GetFileInformationByHandleEx, + (HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, void* lpFileInformation, DWORD dwBufferSize)) { + IO_STATUS_BLOCK IOSB; + return WinAPIReturn(NtQueryInformationFile(hFile, &IOSB, lpFileInformation, dwBufferSize, FileInfoClassToNT(FileInformationClass))); +} + +DLLEXPORT_FUNC(void, GetSystemTimeAsFileTime, (LPFILETIME lpSystemTimeAsFileTime)) { + LARGE_INTEGER Time; + NtQuerySystemTime(&Time); + lpSystemTimeAsFileTime->dwLowDateTime = Time.LowPart; + lpSystemTimeAsFileTime->dwHighDateTime = Time.HighPart; +} + +DLLEXPORT_FUNC(WINBOOL, SetCurrentDirectoryA, (LPCSTR lpPathName)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, SetCurrentDirectoryW, (LPCWSTR lpPathName)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetCurrentDirectoryA, (DWORD nBufferLength, LPSTR lpBuffer)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetCurrentDirectoryW, (DWORD nBufferLength, LPWSTR lpBuffer)) { + return RtlGetCurrentDirectory_U(nBufferLength * sizeof(wchar_t), lpBuffer) / sizeof(wchar_t); +} diff --git a/Source/Windows/Common/WinAPI/Misc.cpp b/Source/Windows/Common/WinAPI/Misc.cpp new file mode 100644 index 000000000..d85b60e8f --- /dev/null +++ b/Source/Windows/Common/WinAPI/Misc.cpp @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT +#define NTDDI_VERSION 0x0A000005 +#define WINAPI +#define WINBASEAPI + +#include +#include +#include +#include +#include +#include +#include +#include "../Priv.h" + +DLLEXPORT_FUNC(HMODULE, GetModuleHandleA, (LPCSTR lpModuleName)) { + ScopedUnicodeString ModuleName {lpModuleName}; + return GetModuleHandleW(ModuleName->Buffer); +} + +DLLEXPORT_FUNC(HMODULE, GetModuleHandleW, (LPCWSTR lpModuleName)) { + HMODULE Res = nullptr; + UNICODE_STRING ModuleName = InitUnicodeString(lpModuleName); + + NTSTATUS Status = LdrGetDllHandle(nullptr, 0, &ModuleName, &Res); + if (Status) { + SetLastError(RtlNtStatusToDosError(Status)); + return nullptr; + } + return Res; +} + +DLLEXPORT_FUNC(FARPROC, GetProcAddress, (HMODULE hModule, LPCSTR lpProcName)) { + void* Res = nullptr; + STRING ProcName = InitAnsiString(lpProcName); + NTSTATUS Status = LdrGetProcedureAddress(hModule, &ProcName, 0, &Res); + if (Status) { + SetLastError(RtlNtStatusToDosError(Status)); + return nullptr; + } + return reinterpret_cast(Res); +} + +DLLEXPORT_FUNC(void, RaiseException, (DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, CONST ULONG_PTR* lpArguments)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(WINBOOL, CloseHandle, (HANDLE hObject)) { + return WinAPIReturn(NtClose(hObject)); +} + +DLLEXPORT_FUNC(WINBOOL, QueryPerformanceCounter, (LARGE_INTEGER * lpPerformanceCount)) { + return RtlQueryPerformanceCounter(lpPerformanceCount); +} + +DLLEXPORT_FUNC(WINBOOL, QueryPerformanceFrequency, (LARGE_INTEGER * lpFrequency)) { + return RtlQueryPerformanceFrequency(lpFrequency); +} + +DLLEXPORT_FUNC(void, GetSystemInfo, (LPSYSTEM_INFO lpSystemInfo)) { + SYSTEM_BASIC_INFORMATION Info; + + if (NtQuerySystemInformation(SystemBasicInformation, &Info, sizeof(Info), nullptr)) { + return; + } + + *lpSystemInfo = SYSTEM_INFO { + .wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64, + .dwPageSize = Info.PhysicalPageSize, + .lpMinimumApplicationAddress = reinterpret_cast(Info.LowestUserAddress), + .lpMaximumApplicationAddress = reinterpret_cast(Info.HighestUserAddress), + .dwActiveProcessorMask = Info.ActiveProcessors, + .dwNumberOfProcessors = static_cast(Info.NumberOfProcessors), + .dwProcessorType = 0, + .dwAllocationGranularity = Info.AllocationGranularity, + .wProcessorLevel = 0, + .wProcessorRevision = 0, + }; +} + +DLLEXPORT_FUNC(int, MultiByteToWideChar, + (UINT CodePage, DWORD dwFlags, LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)) { + DWORD Size = (cbMultiByte == -1) ? (strlen(lpMultiByteStr) + 1) : cbMultiByte; + DWORD Res; + if (!cchWideChar) { + RtlMultiByteToUnicodeSize(&Res, lpMultiByteStr, Size); + } else { + RtlMultiByteToUnicodeN(lpWideCharStr, cchWideChar * sizeof(wchar_t), &Res, lpMultiByteStr, Size); + } + return static_cast(Res / sizeof(wchar_t)); +} + +DLLEXPORT_FUNC(int, WideCharToMultiByte, + (UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, + LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar)) { + DWORD SizeW = ((cchWideChar == -1) ? (wcslen(lpWideCharStr) + 1) : cchWideChar) * sizeof(wchar_t); + DWORD Res; + if (!cbMultiByte) { + RtlUnicodeToMultiByteSize(&Res, const_cast(lpWideCharStr), SizeW); + } else { + RtlUnicodeToMultiByteN(lpMultiByteStr, cbMultiByte, &Res, lpWideCharStr, SizeW); + } + if (lpUsedDefaultChar) { + *lpUsedDefaultChar = false; + } + return static_cast(Res); +} + +DLLEXPORT_FUNC(DWORD, FormatMessageA, + (DWORD dwFlags, const void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, va_list* Arguments)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, FormatMessageW, + (DWORD dwFlags, const void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list* Arguments)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(DWORD, GetLastError, ()) { + return GetCurrentTEB()->LastErrorValue; +} + +DLLEXPORT_FUNC(void, SetLastError, (DWORD dwErrCode)) { + GetCurrentTEB()->LastErrorValue = dwErrCode; +} diff --git a/Source/Windows/Common/WinAPI/Sync.cpp b/Source/Windows/Common/WinAPI/Sync.cpp new file mode 100644 index 000000000..0b5532d34 --- /dev/null +++ b/Source/Windows/Common/WinAPI/Sync.cpp @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT +#define NTDDI_VERSION 0x0A000005 +#define WINAPI +#define WINBASEAPI + +#include +#include +#include +#include +#include +#include +#include +#include "../Priv.h" + +WINBOOL WaitOnAddress(volatile void* Address, void* CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(void, InitializeSRWLock, (PSRWLOCK SRWLock)) { + RtlInitializeSRWLock(SRWLock); +} + +void AcquireSRWLockExclusive(PSRWLOCK SRWLock) { + RtlAcquireSRWLockExclusive(SRWLock); +} + +void ReleaseSRWLockExclusive(PSRWLOCK SRWLock) { + RtlReleaseSRWLockExclusive(SRWLock); +} + +DLLEXPORT_FUNC(BOOLEAN, TryAcquireSRWLockExclusive, (PSRWLOCK SRWLock)) { + return RtlTryAcquireSRWLockExclusive(SRWLock); +} + +DLLEXPORT_FUNC(void, InitializeCriticalSection, (LPCRITICAL_SECTION lpCriticalSection)) { + RtlInitializeCriticalSection(lpCriticalSection); +} + +DLLEXPORT_FUNC(void, EnterCriticalSection, (LPCRITICAL_SECTION lpCriticalSection)) { + RtlEnterCriticalSection(lpCriticalSection); +} + +DLLEXPORT_FUNC(void, LeaveCriticalSection, (LPCRITICAL_SECTION lpCriticalSection)) { + RtlLeaveCriticalSection(lpCriticalSection); +} + +DLLEXPORT_FUNC(WINBOOL, TryEnterCriticalSection, (LPCRITICAL_SECTION lpCriticalSection)) { + return RtlTryEnterCriticalSection(lpCriticalSection); +} + +DLLEXPORT_FUNC(void, DeleteCriticalSection, (LPCRITICAL_SECTION lpCriticalSection)) { + RtlDeleteCriticalSection(lpCriticalSection); +} + +DLLEXPORT_FUNC(void, InitializeConditionVariable, (PCONDITION_VARIABLE ConditionVariable)) { + RtlInitializeConditionVariable(ConditionVariable); +} + +DLLEXPORT_FUNC(void, WakeConditionVariable, (PCONDITION_VARIABLE ConditionVariable)) { + RtlWakeConditionVariable(ConditionVariable); +} + +DLLEXPORT_FUNC(void, WakeAllConditionVariable, (PCONDITION_VARIABLE ConditionVariable)) { + RtlWakeAllConditionVariable(ConditionVariable); +} + +DLLEXPORT_FUNC(WINBOOL, SleepConditionVariableSRW, (PCONDITION_VARIABLE ConditionVariable, PSRWLOCK SRWLock, DWORD dwMilliseconds, ULONG Flags)) { + LARGE_INTEGER Time; + // A negative value indicates a relative time measured in 100ns intervals. + Time.QuadPart = static_cast(dwMilliseconds) * -10000; + return RtlSleepConditionVariableSRW(ConditionVariable, SRWLock, dwMilliseconds == INFINITE ? nullptr : &Time, Flags); +} + +DLLEXPORT_FUNC(WINBOOL, InitOnceExecuteOnce, (PINIT_ONCE InitOnce, PINIT_ONCE_FN InitFn, void* Parameter, void** Context)) { + return !RtlRunOnceExecuteOnce(InitOnce, reinterpret_cast(InitFn), Parameter, Context); +} + +DLLEXPORT_FUNC(DWORD, WaitForSingleObjectEx, (HANDLE hHandle, DWORD dwMilliseconds, WINBOOL bAlertable)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(HANDLE, GetProcessHeap, ()) { + return GetCurrentPEB()->ProcessHeap; +} + +DLLEXPORT_FUNC(DWORD, GetCurrentProcessId, ()) { + return static_cast(reinterpret_cast(GetCurrentTEB()->ClientId.UniqueProcess)); +} + +DLLEXPORT_FUNC(DWORD, GetCurrentThreadId, ()) { + return static_cast(reinterpret_cast(GetCurrentTEB()->ClientId.UniqueThread)); +} + +DLLEXPORT_FUNC(DWORD, GetThreadId, (HANDLE Thread)) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(HANDLE, GetCurrentProcess, ()) { + return NtCurrentProcess(); +} + +DLLEXPORT_FUNC(HANDLE, GetCurrentThread, ()) { + return NtCurrentThread(); +} + +DLLEXPORT_FUNC(DWORD, GetCurrentProcessorNumber, ()) { + return NtGetCurrentProcessorNumber(); +} + +DLLEXPORT_FUNC(WINBOOL, SwitchToThread, ()) { + UNIMPLEMENTED(); +} + +DLLEXPORT_FUNC(void, Sleep, (DWORD dwMilliseconds)) { + UNIMPLEMENTED(); +}