mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
Split kernel32 into separate files (part 3)
This commit is contained in:
parent
fa3ed4893a
commit
2cbd624119
@ -17,6 +17,7 @@
|
||||
- Formatting follows `.clang-format` (LLVM base, tabbed indentation width 4, 120 column limit); never hand-wrap differently.
|
||||
- Use PascalCase for Win32 entry points, camelCase for internal helpers, SCREAMING_SNAKE_CASE for Win32 constants, kCamelCase for internal constants, and g_camelCase for globals.
|
||||
- Put static functions and variables in anonymous namespaces at the top of the file.
|
||||
- Prefer scoping types to the header or source file that uses them; avoid polluting `common.h` unless widely shared.
|
||||
|
||||
## Shim Implementation Guidelines
|
||||
- Target pre-XP behavior; our binaries are old and don't expect modern WinAPI behavior.
|
||||
|
@ -36,25 +36,27 @@ add_executable(wibo
|
||||
dll/bcrypt.cpp
|
||||
dll/crt.cpp
|
||||
dll/kernel32.cpp
|
||||
dll/kernel32/debugapi.cpp
|
||||
dll/kernel32/errhandlingapi.cpp
|
||||
dll/kernel32/fibersapi.cpp
|
||||
dll/kernel32/heapapi.cpp
|
||||
dll/kernel32/memoryapi.cpp
|
||||
dll/kernel32/handleapi.cpp
|
||||
dll/kernel32/fileapi.cpp
|
||||
dll/kernel32/debugapi.cpp
|
||||
dll/kernel32/handleapi.cpp
|
||||
dll/kernel32/heapapi.cpp
|
||||
dll/kernel32/interlockedapi.cpp
|
||||
dll/kernel32/ioapiset.cpp
|
||||
dll/kernel32/libloaderapi.cpp
|
||||
dll/kernel32/winbase.cpp
|
||||
dll/kernel32/wincon.cpp
|
||||
dll/kernel32/memoryapi.cpp
|
||||
dll/kernel32/processenv.cpp
|
||||
dll/kernel32/profileapi.cpp
|
||||
dll/kernel32/processthreadsapi.cpp
|
||||
dll/kernel32/profileapi.cpp
|
||||
dll/kernel32/stringapiset.cpp
|
||||
dll/kernel32/synchapi.cpp
|
||||
dll/kernel32/sysinfoapi.cpp
|
||||
dll/kernel32/timezoneapi.cpp
|
||||
dll/kernel32/synchapi.cpp
|
||||
dll/kernel32/winbase.cpp
|
||||
dll/kernel32/wincon.cpp
|
||||
dll/kernel32/winnls.cpp
|
||||
dll/kernel32/winnt.cpp
|
||||
dll/kernel32/wow64apiset.cpp
|
||||
dll/lmgr.cpp
|
||||
dll/mscoree.cpp
|
||||
|
1037
dll/kernel32.cpp
1037
dll/kernel32.cpp
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,10 @@
|
||||
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "strutil.h"
|
||||
#include "timeutil.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
@ -12,8 +14,12 @@
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <fnmatch.h>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <system_error>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -31,6 +37,48 @@ const FILETIME kDefaultFindFileTime = {
|
||||
static_cast<DWORD>((kSecondsBetween1601And1970 * kWindowsTicksPerSecond) & 0xFFFFFFFFULL),
|
||||
static_cast<DWORD>((kSecondsBetween1601And1970 * kWindowsTicksPerSecond) >> 32)};
|
||||
|
||||
const FILETIME kDefaultFileInformationTime = {static_cast<DWORD>(UNIX_TIME_ZERO & 0xFFFFFFFFULL),
|
||||
static_cast<DWORD>(UNIX_TIME_ZERO >> 32)};
|
||||
|
||||
struct timespec accessTimespec(const struct stat &st) {
|
||||
#if defined(__APPLE__)
|
||||
return st.st_atimespec;
|
||||
#elif defined(__linux__)
|
||||
return st.st_atim;
|
||||
#else
|
||||
struct timespec ts{};
|
||||
ts.tv_sec = st.st_atime;
|
||||
ts.tv_nsec = 0;
|
||||
return ts;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct timespec modifyTimespec(const struct stat &st) {
|
||||
#if defined(__APPLE__)
|
||||
return st.st_mtimespec;
|
||||
#elif defined(__linux__)
|
||||
return st.st_mtim;
|
||||
#else
|
||||
struct timespec ts{};
|
||||
ts.tv_sec = st.st_mtime;
|
||||
ts.tv_nsec = 0;
|
||||
return ts;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct timespec changeTimespec(const struct stat &st) {
|
||||
#if defined(__APPLE__)
|
||||
return st.st_ctimespec;
|
||||
#elif defined(__linux__)
|
||||
return st.st_ctim;
|
||||
#else
|
||||
struct timespec ts{};
|
||||
ts.tv_sec = st.st_ctime;
|
||||
ts.tv_nsec = 0;
|
||||
return ts;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct FindFirstFileHandle {
|
||||
std::filesystem::directory_iterator it;
|
||||
std::filesystem::directory_iterator end;
|
||||
@ -177,6 +225,701 @@ bool initializeEnumeration(const std::filesystem::path &parent, const std::strin
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
int64_t getFileSizeFromHandle(HANDLE hFile) {
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return -1;
|
||||
}
|
||||
struct stat64 st{};
|
||||
fflush(fp);
|
||||
if (fstat64(fileno(fp), &st) == -1 || !S_ISREG(st.st_mode)) {
|
||||
setLastErrorFromErrno();
|
||||
return -1;
|
||||
}
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFileAttributesA(LPCSTR lpFileName) {
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
std::filesystem::path path = files::pathFromWindows(lpFileName);
|
||||
std::string pathStr = path.string();
|
||||
DEBUG_LOG("GetFileAttributesA(%s) -> %s\n", lpFileName, pathStr.c_str());
|
||||
|
||||
if (endsWith(pathStr, "/license.dat")) {
|
||||
DEBUG_LOG("MWCC license override\n");
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
auto status = std::filesystem::status(path, ec);
|
||||
if (ec) {
|
||||
errno = ec.value();
|
||||
setLastErrorFromErrno();
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
switch (status.type()) {
|
||||
case std::filesystem::file_type::regular:
|
||||
DEBUG_LOG("File exists\n");
|
||||
return FILE_ATTRIBUTE_NORMAL;
|
||||
case std::filesystem::file_type::directory:
|
||||
return FILE_ATTRIBUTE_DIRECTORY;
|
||||
case std::filesystem::file_type::not_found:
|
||||
default:
|
||||
DEBUG_LOG("File does not exist\n");
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFileAttributesW(LPCWSTR lpFileName) {
|
||||
DEBUG_LOG("GetFileAttributesW -> ");
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
std::string str = wideStringToString(lpFileName);
|
||||
return GetFileAttributesA(str.c_str());
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DEBUG_LOG("WriteFile(%p, %u)\n", hFile, nNumberOfBytesToWrite);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
|
||||
auto file = files::fileHandleFromHandle(hFile);
|
||||
if (!file || !file->fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool handleOverlapped = (file->flags & FILE_FLAG_OVERLAPPED) != 0;
|
||||
auto *overlapped = reinterpret_cast<OVERLAPPED *>(lpOverlapped);
|
||||
bool usingOverlapped = overlapped != nullptr;
|
||||
if (!usingOverlapped && lpNumberOfBytesWritten == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
std::optional<uint64_t> offset;
|
||||
bool updateFilePointer = true;
|
||||
if (usingOverlapped) {
|
||||
offset = (static_cast<uint64_t>(overlapped->Offset) | (static_cast<uint64_t>(overlapped->OffsetHigh) << 32));
|
||||
overlapped->Internal = STATUS_PENDING;
|
||||
overlapped->InternalHigh = 0;
|
||||
updateFilePointer = !handleOverlapped;
|
||||
resetOverlappedEvent(overlapped);
|
||||
}
|
||||
|
||||
auto io = files::write(file, lpBuffer, nNumberOfBytesToWrite, offset, updateFilePointer);
|
||||
DWORD completionStatus = STATUS_SUCCESS;
|
||||
if (io.unixError != 0) {
|
||||
completionStatus = wibo::winErrorFromErrno(io.unixError);
|
||||
wibo::lastError = completionStatus;
|
||||
if (lpNumberOfBytesWritten) {
|
||||
*lpNumberOfBytesWritten = static_cast<DWORD>(io.bytesTransferred);
|
||||
}
|
||||
if (usingOverlapped) {
|
||||
overlapped->Internal = completionStatus;
|
||||
overlapped->InternalHigh = io.bytesTransferred;
|
||||
signalOverlappedEvent(overlapped);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (lpNumberOfBytesWritten && (!handleOverlapped || !usingOverlapped)) {
|
||||
*lpNumberOfBytesWritten = static_cast<DWORD>(io.bytesTransferred);
|
||||
}
|
||||
|
||||
if (usingOverlapped) {
|
||||
overlapped->Internal = completionStatus;
|
||||
overlapped->InternalHigh = io.bytesTransferred;
|
||||
if (!handleOverlapped) {
|
||||
uint64_t baseOffset = offset.value_or(0);
|
||||
uint64_t newOffset = baseOffset + io.bytesTransferred;
|
||||
overlapped->Offset = static_cast<DWORD>(newOffset & 0xFFFFFFFFu);
|
||||
overlapped->OffsetHigh = static_cast<DWORD>(newOffset >> 32);
|
||||
}
|
||||
signalOverlappedEvent(overlapped);
|
||||
}
|
||||
|
||||
return (io.bytesTransferred == nNumberOfBytesToWrite) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FlushFileBuffers(HANDLE hFile) {
|
||||
DEBUG_LOG("FlushFileBuffers(%p)\n", hFile);
|
||||
auto data = handles::dataFromHandle(hFile, false);
|
||||
if (data.type != handles::TYPE_FILE || data.ptr == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
auto file = reinterpret_cast<files::FileHandle *>(data.ptr);
|
||||
if (!file || !file->fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
FILE *fp = file->fp;
|
||||
if (fflush(fp) != 0) {
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
return FALSE;
|
||||
}
|
||||
int fd = file->fd;
|
||||
if (fd >= 0 && fsync(fd) != 0) {
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DEBUG_LOG("ReadFile(%p, %u)\n", hFile, nNumberOfBytesToRead);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
|
||||
auto file = files::fileHandleFromHandle(hFile);
|
||||
if (!file || !file->fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool handleOverlapped = (file->flags & FILE_FLAG_OVERLAPPED) != 0;
|
||||
auto *overlapped = reinterpret_cast<OVERLAPPED *>(lpOverlapped);
|
||||
bool usingOverlapped = overlapped != nullptr;
|
||||
if (!usingOverlapped && lpNumberOfBytesRead == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
std::optional<uint64_t> offset;
|
||||
bool updateFilePointer = true;
|
||||
if (usingOverlapped) {
|
||||
offset = (static_cast<uint64_t>(overlapped->Offset) | (static_cast<uint64_t>(overlapped->OffsetHigh) << 32));
|
||||
overlapped->Internal = STATUS_PENDING;
|
||||
overlapped->InternalHigh = 0;
|
||||
updateFilePointer = !handleOverlapped;
|
||||
resetOverlappedEvent(overlapped);
|
||||
}
|
||||
|
||||
auto io = files::read(file, lpBuffer, nNumberOfBytesToRead, offset, updateFilePointer);
|
||||
DWORD completionStatus = STATUS_SUCCESS;
|
||||
if (io.unixError != 0) {
|
||||
completionStatus = wibo::winErrorFromErrno(io.unixError);
|
||||
wibo::lastError = completionStatus;
|
||||
if (lpNumberOfBytesRead) {
|
||||
*lpNumberOfBytesRead = static_cast<DWORD>(io.bytesTransferred);
|
||||
}
|
||||
if (usingOverlapped) {
|
||||
overlapped->Internal = completionStatus;
|
||||
overlapped->InternalHigh = io.bytesTransferred;
|
||||
signalOverlappedEvent(overlapped);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (io.reachedEnd && io.bytesTransferred == 0 && handleOverlapped) {
|
||||
completionStatus = ERROR_HANDLE_EOF;
|
||||
}
|
||||
|
||||
if (lpNumberOfBytesRead && (!handleOverlapped || !usingOverlapped)) {
|
||||
*lpNumberOfBytesRead = static_cast<DWORD>(io.bytesTransferred);
|
||||
}
|
||||
|
||||
if (usingOverlapped) {
|
||||
overlapped->Internal = completionStatus;
|
||||
overlapped->InternalHigh = io.bytesTransferred;
|
||||
if (!handleOverlapped) {
|
||||
uint64_t baseOffset = offset.value_or(0);
|
||||
uint64_t newOffset = baseOffset + io.bytesTransferred;
|
||||
overlapped->Offset = static_cast<DWORD>(newOffset & 0xFFFFFFFFu);
|
||||
overlapped->OffsetHigh = static_cast<DWORD>(newOffset >> 32);
|
||||
}
|
||||
signalOverlappedEvent(overlapped);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
(void)lpSecurityAttributes;
|
||||
(void)hTemplateFile;
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
std::string path = files::pathFromWindows(lpFileName);
|
||||
DEBUG_LOG("CreateFileA(filename=%s (%s), desiredAccess=0x%x, shareMode=%u, securityAttributes=%p, "
|
||||
"creationDisposition=%u, flagsAndAttributes=%u)\n",
|
||||
lpFileName, path.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes);
|
||||
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
bool fileExists = (access(path.c_str(), F_OK) == 0);
|
||||
bool shouldTruncate = false;
|
||||
switch (dwCreationDisposition) {
|
||||
case CREATE_ALWAYS:
|
||||
if (fileExists) {
|
||||
wibo::lastError = ERROR_ALREADY_EXISTS;
|
||||
shouldTruncate = true;
|
||||
}
|
||||
break;
|
||||
case CREATE_NEW:
|
||||
if (fileExists) {
|
||||
wibo::lastError = ERROR_FILE_EXISTS;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
break;
|
||||
case OPEN_ALWAYS:
|
||||
if (fileExists) {
|
||||
wibo::lastError = ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
break;
|
||||
case OPEN_EXISTING:
|
||||
if (!fileExists) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
break;
|
||||
case TRUNCATE_EXISTING:
|
||||
shouldTruncate = true;
|
||||
if (!fileExists) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
FILE *fp = nullptr;
|
||||
if (dwDesiredAccess == GENERIC_READ) {
|
||||
fp = fopen(path.c_str(), "rb");
|
||||
} else if (dwDesiredAccess == GENERIC_WRITE) {
|
||||
if (shouldTruncate || !fileExists) {
|
||||
fp = fopen(path.c_str(), "wb");
|
||||
} else {
|
||||
fp = fopen(path.c_str(), "rb+");
|
||||
}
|
||||
} else if (dwDesiredAccess == (GENERIC_READ | GENERIC_WRITE)) {
|
||||
if (shouldTruncate || !fileExists) {
|
||||
fp = fopen(path.c_str(), "wb+");
|
||||
} else {
|
||||
fp = fopen(path.c_str(), "rb+");
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
void *handle = files::allocFpHandle(fp, dwDesiredAccess, dwShareMode, dwFlagsAndAttributes, true);
|
||||
DEBUG_LOG("-> %p\n", handle);
|
||||
return handle;
|
||||
}
|
||||
setLastErrorFromErrno();
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
DEBUG_LOG("CreateFileW -> ");
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
std::string lpFileNameA = wideStringToString(lpFileName);
|
||||
return CreateFileA(lpFileNameA.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC DeleteFileA(LPCSTR lpFileName) {
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
DEBUG_LOG("DeleteFileA(NULL) -> ERROR_INVALID_PARAMETER\n");
|
||||
return FALSE;
|
||||
}
|
||||
std::string path = files::pathFromWindows(lpFileName);
|
||||
DEBUG_LOG("DeleteFileA(%s) -> %s\n", lpFileName, path.c_str());
|
||||
if (unlink(path.c_str()) == 0) {
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC DeleteFileW(LPCWSTR lpFileName) {
|
||||
DEBUG_LOG("DeleteFileW -> ");
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string name = wideStringToString(lpFileName);
|
||||
return DeleteFileA(name.c_str());
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName) {
|
||||
DEBUG_LOG("MoveFileA(%s, %s)\n", lpExistingFileName ? lpExistingFileName : "(null)",
|
||||
lpNewFileName ? lpNewFileName : "(null)");
|
||||
if (!lpExistingFileName || !lpNewFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
auto fromPath = files::pathFromWindows(lpExistingFileName);
|
||||
auto toPath = files::pathFromWindows(lpNewFileName);
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(toPath, ec)) {
|
||||
wibo::lastError = ERROR_ALREADY_EXISTS;
|
||||
return FALSE;
|
||||
}
|
||||
if (ec) {
|
||||
errno = ec.value();
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
std::filesystem::rename(fromPath, toPath, ec);
|
||||
if (ec) {
|
||||
errno = ec.value();
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) {
|
||||
DEBUG_LOG("MoveFileW -> ");
|
||||
if (!lpExistingFileName || !lpNewFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string from = wideStringToString(lpExistingFileName);
|
||||
std::string to = wideStringToString(lpNewFileName);
|
||||
return MoveFileA(from.c_str(), to.c_str());
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
DEBUG_LOG("SetFilePointer(%p, %ld, %p, %u)\n", hFile, static_cast<long>(lDistanceToMove), lpDistanceToMoveHigh,
|
||||
dwMoveMethod);
|
||||
if (hFile == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
int origin = SEEK_SET;
|
||||
if (dwMoveMethod == FILE_CURRENT) {
|
||||
origin = SEEK_CUR;
|
||||
} else if (dwMoveMethod == FILE_END) {
|
||||
origin = SEEK_END;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
if (fseek(fp, lDistanceToMove, origin) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
wibo::lastError = ERROR_NEGATIVE_SEEK;
|
||||
} else {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
long position = ftell(fp);
|
||||
if (position < 0) {
|
||||
setLastErrorFromErrno();
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
if (lpDistanceToMoveHigh) {
|
||||
*lpDistanceToMoveHigh = static_cast<LONG>(static_cast<uint64_t>(position) >> 32);
|
||||
}
|
||||
return static_cast<DWORD>(static_cast<uint64_t>(position) & 0xFFFFFFFFu);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod) {
|
||||
if (hFile == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
int origin = SEEK_SET;
|
||||
if (dwMoveMethod == FILE_CURRENT) {
|
||||
origin = SEEK_CUR;
|
||||
} else if (dwMoveMethod == FILE_END) {
|
||||
origin = SEEK_END;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
if (fseeko(fp, static_cast<off_t>(liDistanceToMove), origin) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
wibo::lastError = ERROR_NEGATIVE_SEEK;
|
||||
} else {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
off_t position = ftello(fp);
|
||||
if (position < 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
if (lpNewFilePointer) {
|
||||
*lpNewFilePointer = static_cast<LARGE_INTEGER>(position);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetEndOfFile(HANDLE hFile) {
|
||||
DEBUG_LOG("SetEndOfFile(%p)\n", hFile);
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
if (fflush(fp) != 0 || ftruncate(fileno(fp), ftell(fp)) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) {
|
||||
(void)lpSecurityAttributes;
|
||||
if (!lpPathName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string path = files::pathFromWindows(lpPathName);
|
||||
DEBUG_LOG("CreateDirectoryA(%s, %p)\n", path.c_str(), lpSecurityAttributes);
|
||||
if (mkdir(path.c_str(), 0755) == 0) {
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC RemoveDirectoryA(LPCSTR lpPathName) {
|
||||
if (!lpPathName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
std::string path = files::pathFromWindows(lpPathName);
|
||||
DEBUG_LOG("RemoveDirectoryA(%s)\n", path.c_str());
|
||||
if (rmdir(path.c_str()) == 0) {
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes) {
|
||||
(void)dwFileAttributes;
|
||||
if (!lpFileName) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
DEBUG_LOG("SetFileAttributesA(%s, %u)\n", lpFileName, dwFileAttributes);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
|
||||
DEBUG_LOG("GetFileSize(%p, %p) ", hFile, lpFileSizeHigh);
|
||||
int64_t size = getFileSizeFromHandle(hFile);
|
||||
if (size < 0) {
|
||||
if (lpFileSizeHigh) {
|
||||
*lpFileSizeHigh = 0;
|
||||
}
|
||||
return INVALID_FILE_SIZE;
|
||||
}
|
||||
uint64_t uSize = static_cast<uint64_t>(size);
|
||||
if (lpFileSizeHigh) {
|
||||
*lpFileSizeHigh = static_cast<DWORD>(uSize >> 32);
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return static_cast<DWORD>(uSize & 0xFFFFFFFFu);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime,
|
||||
LPFILETIME lpLastWriteTime) {
|
||||
DEBUG_LOG("GetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
||||
auto file = files::fileHandleFromHandle(hFile);
|
||||
if (!file || !file->fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
struct stat st{};
|
||||
if (fstat(fileno(file->fp), &st) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
auto assignFileTime = [](LPFILETIME target, const struct timespec &spec) -> bool {
|
||||
if (!target) {
|
||||
return true;
|
||||
}
|
||||
FILETIME result{};
|
||||
uint32_t hundreds = static_cast<uint32_t>(spec.tv_nsec / 100L);
|
||||
if (!unixPartsToFileTime(static_cast<int64_t>(spec.tv_sec), hundreds, result)) {
|
||||
return false;
|
||||
}
|
||||
*target = result;
|
||||
return true;
|
||||
};
|
||||
if (!assignFileTime(lpCreationTime, changeTimespec(st)) || !assignFileTime(lpLastAccessTime, accessTimespec(st)) ||
|
||||
!assignFileTime(lpLastWriteTime, modifyTimespec(st))) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime,
|
||||
const FILETIME *lpLastWriteTime) {
|
||||
DEBUG_LOG("SetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
int fd = fileno(fp);
|
||||
if (fd < 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
bool changeAccess = !shouldIgnoreFileTimeParam(lpLastAccessTime);
|
||||
bool changeWrite = !shouldIgnoreFileTimeParam(lpLastWriteTime);
|
||||
if (!changeAccess && !changeWrite) {
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
struct stat st{};
|
||||
if (fstat(fd, &st) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
struct timespec accessSpec = accessTimespec(st);
|
||||
struct timespec writeSpec = modifyTimespec(st);
|
||||
if (changeAccess) {
|
||||
int64_t seconds = 0;
|
||||
uint32_t hundreds = 0;
|
||||
if (!fileTimeToUnixParts(*lpLastAccessTime, seconds, hundreds) ||
|
||||
!unixPartsToTimespec(seconds, hundreds, accessSpec)) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (changeWrite) {
|
||||
int64_t seconds = 0;
|
||||
uint32_t hundreds = 0;
|
||||
if (!fileTimeToUnixParts(*lpLastWriteTime, seconds, hundreds) ||
|
||||
!unixPartsToTimespec(seconds, hundreds, writeSpec)) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = accessSpec.tv_sec;
|
||||
tv[0].tv_usec = accessSpec.tv_nsec / 1000L;
|
||||
tv[1].tv_sec = writeSpec.tv_sec;
|
||||
tv[1].tv_usec = writeSpec.tv_nsec / 1000L;
|
||||
if (futimes(fd, tv) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
struct timespec times[2] = {accessSpec, writeSpec};
|
||||
if (futimens(fd, times) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
if (!shouldIgnoreFileTimeParam(lpCreationTime) && lpCreationTime) {
|
||||
DEBUG_LOG("SetFileTime: creation time not supported\n");
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation) {
|
||||
DEBUG_LOG("GetFileInformationByHandle(%p, %p)\n", hFile, lpFileInformation);
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
if (fp == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
struct stat64 st{};
|
||||
if (fstat64(fileno(fp), &st) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
return FALSE;
|
||||
}
|
||||
if (lpFileInformation) {
|
||||
lpFileInformation->dwFileAttributes = 0;
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
lpFileInformation->ftCreationTime = kDefaultFileInformationTime;
|
||||
lpFileInformation->ftLastAccessTime = kDefaultFileInformationTime;
|
||||
lpFileInformation->ftLastWriteTime = kDefaultFileInformationTime;
|
||||
lpFileInformation->dwVolumeSerialNumber = 0;
|
||||
lpFileInformation->nFileSizeHigh = static_cast<DWORD>(static_cast<uint64_t>(st.st_size) >> 32);
|
||||
lpFileInformation->nFileSizeLow = static_cast<DWORD>(st.st_size & 0xFFFFFFFFULL);
|
||||
lpFileInformation->nNumberOfLinks = 0;
|
||||
lpFileInformation->nFileIndexHigh = 0;
|
||||
lpFileInformation->nFileIndexLow = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFileType(HANDLE hFile) {
|
||||
DEBUG_LOG("GetFileType(%p) ", hFile);
|
||||
auto *file = files::fileHandleFromHandle(hFile);
|
||||
if (!file || file->fd < 0) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
DEBUG_LOG("-> ERROR_INVALID_HANDLE\n");
|
||||
return FILE_TYPE_UNKNOWN;
|
||||
}
|
||||
struct stat st{};
|
||||
if (fstat(file->fd, &st) != 0) {
|
||||
setLastErrorFromErrno();
|
||||
DEBUG_LOG("-> fstat error\n");
|
||||
return FILE_TYPE_UNKNOWN;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
DWORD type = FILE_TYPE_UNKNOWN;
|
||||
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
|
||||
type = FILE_TYPE_DISK;
|
||||
}
|
||||
if (S_ISCHR(st.st_mode)) {
|
||||
type = FILE_TYPE_CHAR;
|
||||
}
|
||||
if (S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode)) {
|
||||
type = FILE_TYPE_PIPE;
|
||||
}
|
||||
DEBUG_LOG("-> %u\n", type);
|
||||
return type;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR *lpFilePart) {
|
||||
DEBUG_LOG("GetFullPathNameA(%s, %u)\n", lpFileName ? lpFileName : "(null)", nBufferLength);
|
||||
|
||||
|
@ -3,6 +3,58 @@
|
||||
#include "common.h"
|
||||
#include "minwinbase.h"
|
||||
|
||||
struct BY_HANDLE_FILE_INFORMATION {
|
||||
DWORD dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
DWORD dwVolumeSerialNumber;
|
||||
DWORD nFileSizeHigh;
|
||||
DWORD nFileSizeLow;
|
||||
DWORD nNumberOfLinks;
|
||||
DWORD nFileIndexHigh;
|
||||
DWORD nFileIndexLow;
|
||||
};
|
||||
|
||||
using PBY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION *;
|
||||
using LPBY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION *;
|
||||
|
||||
constexpr DWORD GENERIC_READ = 0x80000000;
|
||||
constexpr DWORD GENERIC_WRITE = 0x40000000;
|
||||
constexpr DWORD GENERIC_EXECUTE = 0x20000000;
|
||||
constexpr DWORD GENERIC_ALL = 0x10000000;
|
||||
|
||||
constexpr DWORD FILE_SHARE_READ = 0x00000001;
|
||||
constexpr DWORD FILE_SHARE_WRITE = 0x00000002;
|
||||
constexpr DWORD FILE_SHARE_DELETE = 0x00000004;
|
||||
|
||||
constexpr DWORD CREATE_NEW = 1;
|
||||
constexpr DWORD CREATE_ALWAYS = 2;
|
||||
constexpr DWORD OPEN_EXISTING = 3;
|
||||
constexpr DWORD OPEN_ALWAYS = 4;
|
||||
constexpr DWORD TRUNCATE_EXISTING = 5;
|
||||
|
||||
constexpr DWORD FILE_BEGIN = 0;
|
||||
constexpr DWORD FILE_CURRENT = 1;
|
||||
constexpr DWORD FILE_END = 2;
|
||||
|
||||
constexpr DWORD FILE_ATTRIBUTE_READONLY = 0x00000001;
|
||||
constexpr DWORD FILE_ATTRIBUTE_HIDDEN = 0x00000002;
|
||||
constexpr DWORD FILE_ATTRIBUTE_SYSTEM = 0x00000004;
|
||||
constexpr DWORD FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
|
||||
constexpr DWORD FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
|
||||
constexpr DWORD FILE_ATTRIBUTE_OFFLINE = 0x00001000;
|
||||
constexpr DWORD FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
|
||||
constexpr DWORD FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
|
||||
|
||||
constexpr DWORD FILE_TYPE_UNKNOWN = 0x0000;
|
||||
constexpr DWORD FILE_TYPE_DISK = 0x0001;
|
||||
constexpr DWORD FILE_TYPE_CHAR = 0x0002;
|
||||
constexpr DWORD FILE_TYPE_PIPE = 0x0003;
|
||||
|
||||
constexpr DWORD INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF;
|
||||
constexpr DWORD INVALID_FILE_SIZE = 0xFFFFFFFF;
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
DWORD WIN_FUNC GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR *lpFilePart);
|
||||
@ -18,5 +70,36 @@ HANDLE WIN_FUNC FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLeve
|
||||
BOOL WIN_FUNC FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData);
|
||||
BOOL WIN_FUNC FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData);
|
||||
BOOL WIN_FUNC FindClose(HANDLE hFindFile);
|
||||
DWORD WIN_FUNC GetFileAttributesA(LPCSTR lpFileName);
|
||||
DWORD WIN_FUNC GetFileAttributesW(LPCWSTR lpFileName);
|
||||
BOOL WIN_FUNC WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
BOOL WIN_FUNC ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
BOOL WIN_FUNC FlushFileBuffers(HANDLE hFile);
|
||||
HANDLE WIN_FUNC CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
HANDLE WIN_FUNC CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
BOOL WIN_FUNC DeleteFileA(LPCSTR lpFileName);
|
||||
BOOL WIN_FUNC DeleteFileW(LPCWSTR lpFileName);
|
||||
BOOL WIN_FUNC MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName);
|
||||
BOOL WIN_FUNC MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName);
|
||||
DWORD WIN_FUNC SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
BOOL WIN_FUNC SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod);
|
||||
BOOL WIN_FUNC SetEndOfFile(HANDLE hFile);
|
||||
BOOL WIN_FUNC CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
|
||||
BOOL WIN_FUNC RemoveDirectoryA(LPCSTR lpPathName);
|
||||
BOOL WIN_FUNC SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes);
|
||||
DWORD WIN_FUNC GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
|
||||
BOOL WIN_FUNC GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime,
|
||||
LPFILETIME lpLastWriteTime);
|
||||
BOOL WIN_FUNC SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime,
|
||||
const FILETIME *lpLastWriteTime);
|
||||
BOOL WIN_FUNC GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||
DWORD WIN_FUNC GetFileType(HANDLE hFile);
|
||||
|
||||
} // namespace kernel32
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "minwinbase.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
@ -56,6 +58,7 @@ void signalOverlappedEvent(OVERLAPPED *ov);
|
||||
void tryMarkExecutable(void *mem);
|
||||
void setLastErrorFromErrno();
|
||||
bool closeFileMappingHandle(void *mappingPtr);
|
||||
int64_t getFileSizeFromHandle(HANDLE hFile);
|
||||
ThreadObject *ensureCurrentThreadObject();
|
||||
ThreadObject *threadObjectFromHandle(HANDLE hThread);
|
||||
ThreadObject *retainThreadObject(ThreadObject *obj);
|
||||
|
49
dll/kernel32/ioapiset.cpp
Normal file
49
dll/kernel32/ioapiset.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "ioapiset.h"
|
||||
|
||||
#include "errors.h"
|
||||
#include "synchapi.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred,
|
||||
BOOL bWait) {
|
||||
DEBUG_LOG("GetOverlappedResult(%p, %p, %p, %d)\n", hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait);
|
||||
(void)hFile;
|
||||
if (!lpOverlapped) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
if (bWait && lpOverlapped->Internal == STATUS_PENDING) {
|
||||
if (lpOverlapped->hEvent) {
|
||||
WaitForSingleObject(lpOverlapped->hEvent, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
const auto status = static_cast<NTSTATUS>(lpOverlapped->Internal);
|
||||
if (status == STATUS_PENDING) {
|
||||
wibo::lastError = ERROR_IO_INCOMPLETE;
|
||||
if (lpNumberOfBytesTransferred) {
|
||||
*lpNumberOfBytesTransferred = static_cast<DWORD>(lpOverlapped->InternalHigh);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (lpNumberOfBytesTransferred) {
|
||||
*lpNumberOfBytesTransferred = static_cast<DWORD>(lpOverlapped->InternalHigh);
|
||||
}
|
||||
|
||||
if (status == STATUS_SUCCESS) {
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
if (status == STATUS_END_OF_FILE || status == ERROR_HANDLE_EOF) {
|
||||
wibo::lastError = ERROR_HANDLE_EOF;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wibo::lastError = status;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
||||
|
12
dll/kernel32/ioapiset.h
Normal file
12
dll/kernel32/ioapiset.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "minwinbase.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred,
|
||||
BOOL bWait);
|
||||
|
||||
} // namespace kernel32
|
||||
|
@ -19,10 +19,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace kernel32 {
|
||||
int64_t getFileSize(HANDLE hFile);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t kVirtualAllocationGranularity = 64 * 1024;
|
||||
@ -285,7 +281,7 @@ HANDLE WIN_FUNC CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMap
|
||||
}
|
||||
mapping->fd = dupFd;
|
||||
if (size == 0) {
|
||||
int64_t fileSize = getFileSize(hFile);
|
||||
int64_t fileSize = getFileSizeFromHandle(hFile);
|
||||
if (fileSize < 0) {
|
||||
closeMappingIfPossible(mapping);
|
||||
return nullptr;
|
||||
|
@ -103,6 +103,21 @@ template <typename StartupInfo> void populateStartupInfo(StartupInfo *info) {
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC IsProcessorFeaturePresent(DWORD ProcessorFeature) {
|
||||
DEBUG_LOG("IsProcessorFeaturePresent(%u)\n", ProcessorFeature);
|
||||
if (ProcessorFeature == 0) { // PF_FLOATING_POINT_PRECISION_ERRATA
|
||||
return TRUE;
|
||||
}
|
||||
if (ProcessorFeature == 10) { // PF_XMMI64_INSTRUCTIONS_AVAILABLE (SSE2)
|
||||
return TRUE;
|
||||
}
|
||||
if (ProcessorFeature == 23) { // PF_FASTFAIL_AVAILABLE (__fastfail() supported)
|
||||
return TRUE;
|
||||
}
|
||||
DEBUG_LOG(" IsProcessorFeaturePresent: unknown feature %u, returning TRUE\n", ProcessorFeature);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
thread_local ThreadObject *g_currentThreadObject = nullptr;
|
||||
|
||||
ThreadObject *ensureCurrentThreadObject() {
|
||||
|
@ -70,6 +70,7 @@ HANDLE WIN_FUNC GetCurrentProcess();
|
||||
DWORD WIN_FUNC GetCurrentProcessId();
|
||||
DWORD WIN_FUNC GetCurrentThreadId();
|
||||
HANDLE WIN_FUNC GetCurrentThread();
|
||||
BOOL WIN_FUNC IsProcessorFeaturePresent(DWORD ProcessorFeature);
|
||||
BOOL WIN_FUNC GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask,
|
||||
PDWORD_PTR lpSystemAffinityMask);
|
||||
BOOL WIN_FUNC SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask);
|
||||
|
@ -38,6 +38,11 @@ void makeWideNameFromAnsi(LPCSTR ansiName, std::vector<uint16_t> &outWide) {
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
void WIN_FUNC Sleep(DWORD dwMilliseconds) {
|
||||
DEBUG_LOG("Sleep(%u)\n", dwMilliseconds);
|
||||
usleep(static_cast<useconds_t>(dwMilliseconds) * 1000);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::mutex mutexRegistryLock;
|
||||
|
@ -73,6 +73,7 @@ constexpr SRWLOCK SRWLOCK_INIT{nullptr};
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
void WIN_FUNC Sleep(DWORD dwMilliseconds);
|
||||
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);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "strutil.h"
|
||||
|
||||
@ -9,6 +10,7 @@
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <limits>
|
||||
@ -154,10 +156,95 @@ bool resolveDiskFreeSpaceStat(const char *rootPathName, struct statvfs &outBuf,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr DWORD kComputerNameLength = 8;
|
||||
constexpr DWORD kComputerNameRequiredSize = kComputerNameLength + 1;
|
||||
constexpr const char kComputerNameAnsi[] = "COMPNAME";
|
||||
const uint16_t kComputerNameWide[] = {u'C', u'O', u'M', u'P', u'N', u'A', u'M', u'E', 0};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
UINT WIN_FUNC SetHandleCount(UINT uNumber) {
|
||||
DEBUG_LOG("SetHandleCount(%u)\n", uNumber);
|
||||
(void)uNumber;
|
||||
return handles::MAX_HANDLES;
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId,
|
||||
LPSTR lpBuffer, DWORD nSize, va_list *Arguments) {
|
||||
DEBUG_LOG("FormatMessageA(%u, %p, %u, %u, %p, %u, %p)\n", dwFlags, lpSource, dwMessageId, dwLanguageId,
|
||||
lpBuffer, nSize, Arguments);
|
||||
|
||||
if (dwFlags & 0x00000100) {
|
||||
// FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
} else if (dwFlags & 0x00002000) {
|
||||
// FORMAT_MESSAGE_ARGUMENT_ARRAY
|
||||
} else if (dwFlags & 0x00000800) {
|
||||
// FORMAT_MESSAGE_FROM_HMODULE
|
||||
} else if (dwFlags & 0x00000400) {
|
||||
// FORMAT_MESSAGE_FROM_STRING
|
||||
} else if (dwFlags & 0x00001000) {
|
||||
// FORMAT_MESSAGE_FROM_SYSTEM
|
||||
std::string message = std::system_category().message(static_cast<int>(dwMessageId));
|
||||
size_t length = message.length();
|
||||
if (!lpBuffer || nSize == 0) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return 0;
|
||||
}
|
||||
std::strncpy(lpBuffer, message.c_str(), static_cast<size_t>(nSize));
|
||||
if (static_cast<size_t>(nSize) <= length) {
|
||||
if (static_cast<size_t>(nSize) > 0) {
|
||||
lpBuffer[nSize - 1] = '\0';
|
||||
}
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return 0;
|
||||
}
|
||||
lpBuffer[length] = '\0';
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return static_cast<DWORD>(length);
|
||||
} else if (dwFlags & 0x00000200) {
|
||||
// FORMAT_MESSAGE_IGNORE_INSERTS
|
||||
} else {
|
||||
// unhandled?
|
||||
}
|
||||
|
||||
if (lpBuffer && nSize > 0) {
|
||||
lpBuffer[0] = '\0';
|
||||
}
|
||||
wibo::lastError = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVOID WIN_FUNC EncodePointer(PVOID Ptr) {
|
||||
DEBUG_LOG("EncodePointer(%p)\n", Ptr);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
PVOID WIN_FUNC DecodePointer(PVOID Ptr) {
|
||||
DEBUG_LOG("DecodePointer(%p)\n", Ptr);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetDllDirectoryA(LPCSTR lpPathName) {
|
||||
DEBUG_LOG("SetDllDirectoryA(%s)\n", lpPathName);
|
||||
if (!lpPathName || lpPathName[0] == '\0') {
|
||||
wibo::clearDllDirectoryOverride();
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::filesystem::path hostPath = files::pathFromWindows(lpPathName);
|
||||
if (hostPath.empty() || !std::filesystem::exists(hostPath)) {
|
||||
wibo::lastError = ERROR_PATH_NOT_FOUND;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wibo::setDllDirectoryOverride(std::filesystem::absolute(hostPath));
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void tryMarkExecutable(void *mem) {
|
||||
if (!mem) {
|
||||
return;
|
||||
@ -196,6 +283,50 @@ BOOL WIN_FUNC IsBadWritePtr(LPVOID lp, UINT_PTR ucb) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize) {
|
||||
DEBUG_LOG("GetComputerNameA(%p, %p)\n", lpBuffer, nSize);
|
||||
if (!nSize || !lpBuffer) {
|
||||
if (nSize) {
|
||||
*nSize = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*nSize < kComputerNameRequiredSize) {
|
||||
*nSize = kComputerNameRequiredSize;
|
||||
wibo::lastError = ERROR_BUFFER_OVERFLOW;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
std::strcpy(lpBuffer, kComputerNameAnsi);
|
||||
*nSize = kComputerNameLength;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize) {
|
||||
DEBUG_LOG("GetComputerNameW(%p, %p)\n", lpBuffer, nSize);
|
||||
if (!nSize || !lpBuffer) {
|
||||
if (nSize) {
|
||||
*nSize = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*nSize < kComputerNameRequiredSize) {
|
||||
*nSize = kComputerNameRequiredSize;
|
||||
wibo::lastError = ERROR_BUFFER_OVERFLOW;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wstrncpy(lpBuffer, kComputerNameWide, static_cast<size_t>(kComputerNameRequiredSize));
|
||||
*nSize = kComputerNameLength;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HGLOBAL WIN_FUNC GlobalAlloc(UINT uFlags, SIZE_T dwBytes) {
|
||||
VERBOSE_LOG("GlobalAlloc(%x, %zu)\n", uFlags, static_cast<size_t>(dwBytes));
|
||||
if (uFlags & GMEM_MOVEABLE) {
|
||||
|
@ -2,10 +2,21 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC IsBadReadPtr(LPCVOID lp, UINT_PTR ucb);
|
||||
BOOL WIN_FUNC IsBadWritePtr(LPVOID lp, UINT_PTR ucb);
|
||||
UINT WIN_FUNC SetHandleCount(UINT uNumber);
|
||||
DWORD WIN_FUNC FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId,
|
||||
LPSTR lpBuffer, DWORD nSize, va_list *Arguments);
|
||||
PVOID WIN_FUNC EncodePointer(PVOID Ptr);
|
||||
PVOID WIN_FUNC DecodePointer(PVOID Ptr);
|
||||
BOOL WIN_FUNC SetDllDirectoryA(LPCSTR lpPathName);
|
||||
|
||||
BOOL WIN_FUNC GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize);
|
||||
BOOL WIN_FUNC GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize);
|
||||
|
||||
HGLOBAL WIN_FUNC GlobalAlloc(UINT uFlags, SIZE_T dwBytes);
|
||||
HGLOBAL WIN_FUNC GlobalFree(HGLOBAL hMem);
|
||||
|
13
dll/kernel32/winnt.cpp
Normal file
13
dll/kernel32/winnt.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "winnt.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
void WIN_FUNC RtlUnwind(PVOID TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue) {
|
||||
DEBUG_LOG("RtlUnwind(%p, %p, %p, %p)\n", TargetFrame, TargetIp, ExceptionRecord, ReturnValue);
|
||||
DEBUG_LOG("WARNING: Silently returning from RtlUnwind - exception handlers and clean up code may not be run\n");
|
||||
}
|
||||
|
||||
} // namespace kernel32
|
||||
|
11
dll/kernel32/winnt.h
Normal file
11
dll/kernel32/winnt.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "errhandlingapi.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
void WIN_FUNC RtlUnwind(PVOID TargetFrame, PVOID TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue);
|
||||
|
||||
} // namespace kernel32
|
||||
|
7
errors.h
7
errors.h
@ -9,6 +9,7 @@
|
||||
#define ERROR_INVALID_HANDLE 6
|
||||
#define ERROR_NOT_ENOUGH_MEMORY 8
|
||||
#define ERROR_NO_MORE_FILES 18
|
||||
#define ERROR_FILE_EXISTS 80
|
||||
#define ERROR_READ_FAULT 30
|
||||
#define ERROR_HANDLE_EOF 38
|
||||
#define ERROR_INVALID_ADDRESS 487
|
||||
@ -35,8 +36,8 @@
|
||||
#define ERROR_ALREADY_EXISTS 183
|
||||
#define ERROR_NOT_OWNER 288
|
||||
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD) - 1)
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE) - 1)
|
||||
|
||||
typedef int NTSTATUS;
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
||||
@ -54,4 +55,4 @@ typedef int HRESULT;
|
||||
namespace wibo {
|
||||
DWORD winErrorFromErrno(int err);
|
||||
NTSTATUS statusFromWinError(DWORD error);
|
||||
}
|
||||
} // namespace wibo
|
||||
|
Loading…
x
Reference in New Issue
Block a user