mirror of
https://github.com/ptitSeb/box64.git
synced 2025-08-29 01:53:47 +02:00
312 lines
9.8 KiB
C
312 lines
9.8 KiB
C
#include <stddef.h>
|
|
#include <windows.h>
|
|
#include <ntstatus.h>
|
|
#include <winternl.h>
|
|
|
|
#include "debug.h"
|
|
#include "wine/compiler.h"
|
|
#include "wine/debug.h"
|
|
|
|
|
|
#define FILE_ATTRIBUTE_VALID_FLAGS 0x00007fb7
|
|
|
|
static UINT get_nt_file_options(DWORD attributes)
|
|
{
|
|
UINT options = 0;
|
|
|
|
if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
|
|
options |= FILE_OPEN_FOR_BACKUP_INTENT;
|
|
else
|
|
options |= FILE_NON_DIRECTORY_FILE;
|
|
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
|
|
options |= FILE_DELETE_ON_CLOSE;
|
|
if (attributes & FILE_FLAG_NO_BUFFERING)
|
|
options |= FILE_NO_INTERMEDIATE_BUFFERING;
|
|
if (!(attributes & FILE_FLAG_OVERLAPPED))
|
|
options |= FILE_SYNCHRONOUS_IO_NONALERT;
|
|
if (attributes & FILE_FLAG_RANDOM_ACCESS)
|
|
options |= FILE_RANDOM_ACCESS;
|
|
if (attributes & FILE_FLAG_SEQUENTIAL_SCAN)
|
|
options |= FILE_SEQUENTIAL_ONLY;
|
|
if (attributes & FILE_FLAG_WRITE_THROUGH)
|
|
options |= FILE_WRITE_THROUGH;
|
|
return options;
|
|
}
|
|
|
|
HANDLE WINAPI CreateFileW(LPCWSTR filename, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa, DWORD creation, DWORD attributes, HANDLE template)
|
|
{
|
|
UNICODE_STRING filenameU;
|
|
OBJECT_ATTRIBUTES attr;
|
|
IO_STATUS_BLOCK io;
|
|
HANDLE ret;
|
|
|
|
static const UINT nt_disposition[5] = { FILE_CREATE, FILE_OVERWRITE_IF, FILE_OPEN, FILE_OPEN_IF, FILE_OVERWRITE };
|
|
if (!RtlDosPathNameToNtPathName_U(filename, &filenameU, NULL, NULL)) {
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
if (attributes & FILE_FLAG_DELETE_ON_CLOSE) access |= DELETE;
|
|
InitializeObjectAttributes(&attr, &filenameU, OBJ_CASE_INSENSITIVE, 0, NULL);
|
|
NTSTATUS status = NtCreateFile(&ret, access | GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, attributes & FILE_ATTRIBUTE_VALID_FLAGS, sharing,
|
|
nt_disposition[creation - CREATE_NEW], get_nt_file_options(attributes), NULL, 0);
|
|
RtlFreeUnicodeString(&filenameU);
|
|
return status ? INVALID_HANDLE_VALUE : ret;
|
|
}
|
|
|
|
HANDLE WINAPI CreateFileA(LPCSTR name, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa, DWORD creation, DWORD attributes, HANDLE template)
|
|
{
|
|
UNICODE_STRING nameU;
|
|
RtlCreateUnicodeStringFromAsciiz(&nameU, name);
|
|
HANDLE handle = CreateFileW(nameU.Buffer, access, sharing, sa, creation, attributes, template);
|
|
RtlFreeUnicodeString(&nameU);
|
|
return handle;
|
|
}
|
|
|
|
|
|
BOOL WINAPI CloseHandle(HANDLE handle)
|
|
{
|
|
return !NtClose(handle);
|
|
}
|
|
|
|
DWORD WINAPI GetEnvironmentVariableA(LPCSTR name, LPSTR value, DWORD size)
|
|
{
|
|
UNICODE_STRING nameU, valueU;
|
|
PWSTR valueW;
|
|
NTSTATUS status;
|
|
DWORD len, ret;
|
|
|
|
if (!(valueW = RtlAllocateHeap(GetProcessHeap(), 0, size * sizeof(WCHAR)))) return 0;
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&nameU, name);
|
|
valueU.Length = 0;
|
|
valueU.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
|
|
valueU.Buffer = valueW;
|
|
|
|
status = RtlQueryEnvironmentVariable_U(NULL, &nameU, &valueU);
|
|
len = valueU.Length / sizeof(WCHAR);
|
|
if (status == STATUS_BUFFER_TOO_SMALL)
|
|
ret = len + 1;
|
|
else if (status)
|
|
ret = 0;
|
|
else if (!size)
|
|
ret = len + 1;
|
|
else {
|
|
if (len) RtlUnicodeToMultiByteN(value, size, &ret, valueW, len * sizeof(WCHAR));
|
|
}
|
|
|
|
RtlFreeUnicodeString(&nameU);
|
|
RtlFreeHeap(GetProcessHeap(), 0, valueW);
|
|
return ret;
|
|
}
|
|
|
|
DWORD WINAPI GetFileAttributesW(LPCWSTR name)
|
|
{
|
|
FILE_BASIC_INFORMATION info;
|
|
UNICODE_STRING nameU;
|
|
OBJECT_ATTRIBUTES attr;
|
|
NTSTATUS status;
|
|
|
|
if (!RtlDosPathNameToNtPathName_U(name, &nameU, NULL, NULL)) {
|
|
return INVALID_FILE_ATTRIBUTES;
|
|
}
|
|
|
|
InitializeObjectAttributes(&attr, &nameU, OBJ_CASE_INSENSITIVE, 0, NULL);
|
|
status = NtQueryAttributesFile(&attr, &info);
|
|
RtlFreeUnicodeString(&nameU);
|
|
|
|
if (status == STATUS_SUCCESS) return info.FileAttributes;
|
|
if (RtlIsDosDeviceName_U(name)) return FILE_ATTRIBUTE_ARCHIVE;
|
|
return INVALID_FILE_ATTRIBUTES;
|
|
}
|
|
|
|
DWORD WINAPI GetFileAttributesA(LPCSTR name)
|
|
{
|
|
UNICODE_STRING nameU;
|
|
RtlCreateUnicodeStringFromAsciiz(&nameU, name);
|
|
DWORD ret = GetFileAttributesW(nameU.Buffer);
|
|
RtlFreeUnicodeString(&nameU);
|
|
return ret;
|
|
}
|
|
|
|
HANDLE WINAPI GetProcessHeap(void)
|
|
{
|
|
return ((HANDLE**)NtCurrentTeb())[12][6];
|
|
}
|
|
|
|
|
|
DWORD WINAPI GetModuleFileNameW(HMODULE module, LPWSTR filename, DWORD size)
|
|
{
|
|
ULONG len = 0;
|
|
UNICODE_STRING filenameU;
|
|
NTSTATUS status;
|
|
|
|
filenameU.Buffer = filename;
|
|
filenameU.MaximumLength = min(size, UNICODE_STRING_MAX_CHARS) * sizeof(WCHAR);
|
|
status = LdrGetDllFullName(module, &filenameU);
|
|
if (!status || status == STATUS_BUFFER_TOO_SMALL) len = filenameU.Length / sizeof(WCHAR);
|
|
return len;
|
|
}
|
|
|
|
|
|
DWORD WINAPI GetModuleFileNameA(HMODULE module, LPSTR filename, DWORD size)
|
|
{
|
|
LPWSTR filenameW = RtlAllocateHeap(GetProcessHeap(), 0, size * sizeof(WCHAR));
|
|
DWORD len, ret = 0;
|
|
|
|
if (!filenameW) return 0;
|
|
|
|
if ((len = GetModuleFileNameW(module, filenameW, size))) {
|
|
RtlUnicodeToMultiByteN(filename, size, &ret, filenameW, len * sizeof(WCHAR));
|
|
if (ret < size) filename[ret] = 0;
|
|
}
|
|
RtlFreeHeap(GetProcessHeap(), 0, filenameW);
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI ReadFile(HANDLE file, LPVOID buffer, DWORD count, LPDWORD result, LPOVERLAPPED overlapped)
|
|
{
|
|
LARGE_INTEGER offset;
|
|
PLARGE_INTEGER poffset = NULL;
|
|
IO_STATUS_BLOCK iosb;
|
|
PIO_STATUS_BLOCK io_status = &iosb;
|
|
HANDLE event = 0;
|
|
NTSTATUS status;
|
|
LPVOID cvalue = NULL;
|
|
|
|
if (result) *result = 0;
|
|
|
|
if (overlapped) {
|
|
printf_log(LOG_NONE, "unimplemented overlapped in ReadFile\n");
|
|
return FALSE;
|
|
} else
|
|
io_status->Information = 0;
|
|
io_status->Status = STATUS_PENDING;
|
|
|
|
status = NtReadFile(file, event, NULL, cvalue, io_status, buffer, count, poffset, NULL);
|
|
|
|
if (status == STATUS_PENDING && !overlapped) {
|
|
printf_log(LOG_NONE, "unimplemented pending in ReadFile\n");
|
|
}
|
|
|
|
if (result) *result = overlapped && status ? 0 : io_status->Information;
|
|
|
|
if (status == STATUS_END_OF_FILE) {
|
|
if (overlapped != NULL) {
|
|
return FALSE;
|
|
}
|
|
} else if (status && status != STATUS_TIMEOUT) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void fillSystemInfo(SYSTEM_INFO* si, const SYSTEM_BASIC_INFORMATION__* basic_info, const SYSTEM_CPU_INFORMATION* cpu_info)
|
|
{
|
|
si->wProcessorArchitecture = cpu_info->ProcessorArchitecture;
|
|
si->wReserved = 0;
|
|
si->dwPageSize = basic_info->PageSize;
|
|
si->lpMinimumApplicationAddress = basic_info->LowestUserAddress;
|
|
si->lpMaximumApplicationAddress = basic_info->HighestUserAddress;
|
|
si->dwActiveProcessorMask = basic_info->ActiveProcessorsAffinityMask;
|
|
si->dwNumberOfProcessors = basic_info->NumberOfProcessors;
|
|
si->dwAllocationGranularity = basic_info->AllocationGranularity;
|
|
si->wProcessorLevel = cpu_info->ProcessorLevel;
|
|
si->wProcessorRevision = cpu_info->ProcessorRevision;
|
|
|
|
switch (cpu_info->ProcessorArchitecture) {
|
|
case PROCESSOR_ARCHITECTURE_ARM64:
|
|
si->dwProcessorType = 0;
|
|
break;
|
|
default:
|
|
printf_log(LOG_NONE, "Unknown processor architecture %x\n", cpu_info->ProcessorArchitecture);
|
|
si->dwProcessorType = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WINAPI GetSystemInfo(SYSTEM_INFO* si)
|
|
{
|
|
SYSTEM_BASIC_INFORMATION__ basic_info;
|
|
SYSTEM_CPU_INFORMATION cpu_info;
|
|
|
|
if (NtQuerySystemInformation(0 /* SystemBasicInformation */, &basic_info, sizeof(basic_info), NULL)
|
|
|| NtQuerySystemInformation(1 /* SystemCpuInformation */, &cpu_info, sizeof(cpu_info), NULL))
|
|
return;
|
|
|
|
fillSystemInfo(si, &basic_info, &cpu_info);
|
|
}
|
|
|
|
BOOL WINAPI IsProcessorFeaturePresent(DWORD feature)
|
|
{
|
|
return RtlIsProcessorFeaturePresent(feature);
|
|
}
|
|
|
|
LSTATUS WINAPI RegOpenKeyExA(HKEY hkey, LPCSTR name, DWORD options, REGSAM access, PHKEY retkey)
|
|
{
|
|
if (hkey != HKEY_LOCAL_MACHINE) {
|
|
printf_log(LOG_NONE, "Unsupported registry key %p\n", hkey);
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
UNICODE_STRING rootkeyU;
|
|
UNICODE_STRING nameU;
|
|
OBJECT_ATTRIBUTES attr;
|
|
NTSTATUS status;
|
|
HANDLE handle;
|
|
RtlInitUnicodeString(&rootkeyU, L"\\Registry\\Machine");
|
|
InitializeObjectAttributes(&attr, &rootkeyU, OBJ_CASE_INSENSITIVE, 0, NULL);
|
|
if (NtOpenKey(&handle, access, &attr)) return RtlNtStatusToDosError(status);
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&nameU, name);
|
|
InitializeObjectAttributes(&attr, &nameU, OBJ_CASE_INSENSITIVE, handle, NULL);
|
|
status = NtOpenKey((HANDLE*)retkey, access, &attr);
|
|
RtlFreeUnicodeString(&nameU);
|
|
NtClose(handle);
|
|
return RtlNtStatusToDosError(status);
|
|
}
|
|
|
|
LSTATUS WINAPI RegQueryValueExA(HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
|
|
{
|
|
NTSTATUS status;
|
|
ANSI_STRING nameA;
|
|
UNICODE_STRING nameW;
|
|
DWORD total_size, datalen = 0;
|
|
char buffer[256];
|
|
KEY_VALUE_PARTIAL_INFORMATION* info = (KEY_VALUE_PARTIAL_INFORMATION*)buffer;
|
|
static const int info_size = offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data);
|
|
|
|
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
|
|
|
|
if (count) datalen = *count;
|
|
if (!data && count) *count = 0;
|
|
|
|
RtlInitAnsiString(&nameA, name);
|
|
if ((status = RtlAnsiStringToUnicodeString(&nameW, &nameA, TRUE)))
|
|
return RtlNtStatusToDosError(status);
|
|
|
|
status = NtQueryValueKey(hkey, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &total_size);
|
|
if (status) {
|
|
RtlFreeUnicodeString(&nameW);
|
|
return RtlNtStatusToDosError(status);
|
|
}
|
|
|
|
if (data) {
|
|
if (total_size - info_size > datalen)
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
else
|
|
memcpy(data, buffer + info_size, total_size - info_size);
|
|
} else
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (type) *type = info->Type;
|
|
if (count) *count = total_size - info_size;
|
|
|
|
RtlFreeUnicodeString(&nameW);
|
|
return RtlNtStatusToDosError(status);
|
|
}
|
|
|
|
LSTATUS WINAPI RegCloseKey(HKEY hkey)
|
|
{
|
|
if (!hkey) return ERROR_INVALID_HANDLE;
|
|
return RtlNtStatusToDosError(NtClose(hkey));
|
|
}
|