about summary refs log tree commit diff stats
path: root/wine/common/wrt.c
diff options
context:
space:
mode:
Diffstat (limited to 'wine/common/wrt.c')
-rw-r--r--wine/common/wrt.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/wine/common/wrt.c b/wine/common/wrt.c
new file mode 100644
index 00000000..d9725e4b
--- /dev/null
+++ b/wine/common/wrt.c
@@ -0,0 +1,236 @@
+#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);
+}