Revert tree-restructure attempt: r66583, r66582, r66581, r66578, sauf ntdll changes...
[reactos.git] / reactos / dll / win32 / kernel32 / client / utils.c
diff --git a/reactos/dll/win32/kernel32/client/utils.c b/reactos/dll/win32/kernel32/client/utils.c
new file mode 100644 (file)
index 0000000..f82437f
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/kernel32/misc/utils.c
+ * PURPOSE:         Utility and Support Functions
+ * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
+ *                  Pierre Schweitzer (pierre.schweitzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <k32.h>
+#ifdef _M_IX86
+#include "i386/ketypes.h"
+#elif defined _M_AMD64
+#include "amd64/ketypes.h"
+#endif
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+UNICODE_STRING Restricted = RTL_CONSTANT_STRING(L"Restricted");
+BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
+PRTL_CONVERT_STRING Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
+PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
+PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
+PRTL_COUNT_STRINGA Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
+
+/* FUNCTIONS ******************************************************************/
+
+ULONG
+NTAPI
+BasepUnicodeStringToOemSize(IN PUNICODE_STRING String)
+{
+    return RtlUnicodeStringToOemSize(String);
+}
+
+ULONG
+NTAPI
+BasepOemStringToUnicodeSize(IN PANSI_STRING String)
+{
+    return RtlOemStringToUnicodeSize(String);
+}
+
+ULONG
+NTAPI
+BasepUnicodeStringToAnsiSize(IN PUNICODE_STRING String)
+{
+    return RtlUnicodeStringToAnsiSize(String);
+}
+
+ULONG
+NTAPI
+BasepAnsiStringToUnicodeSize(IN PANSI_STRING String)
+{
+    return RtlAnsiStringToUnicodeSize(String);
+}
+
+HANDLE
+WINAPI
+BaseGetNamedObjectDirectory(VOID)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE DirHandle, BnoHandle, Token, NewToken;
+
+    if (BaseNamedObjectDirectory) return BaseNamedObjectDirectory;
+
+    if (NtCurrentTeb()->IsImpersonating)
+    {
+        Status = NtOpenThreadToken(NtCurrentThread(),
+                                   TOKEN_IMPERSONATE,
+                                   TRUE,
+                                   &Token);
+        if (!NT_SUCCESS(Status)) return BaseNamedObjectDirectory;
+
+        NewToken = NULL;
+        Status = NtSetInformationThread(NtCurrentThread(),
+                                        ThreadImpersonationToken,
+                                        &NewToken,
+                                        sizeof(HANDLE));
+        if (!NT_SUCCESS (Status))
+        {
+            NtClose(Token);
+            return BaseNamedObjectDirectory;
+        }
+    }
+    else
+    {
+        Token = NULL;
+    }
+
+    RtlAcquirePebLock();
+    if (BaseNamedObjectDirectory) goto Quickie;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &BaseStaticServerData->NamedObjectDirectory,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenDirectoryObject(&BnoHandle,
+                                   DIRECTORY_QUERY |
+                                   DIRECTORY_TRAVERSE |
+                                   DIRECTORY_CREATE_OBJECT |
+                                   DIRECTORY_CREATE_SUBDIRECTORY,
+                                   &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        Status = NtOpenDirectoryObject(&DirHandle,
+                                       DIRECTORY_TRAVERSE,
+                                       &ObjectAttributes);
+
+        if (NT_SUCCESS(Status))
+        {
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       (PUNICODE_STRING)&Restricted,
+                                       OBJ_CASE_INSENSITIVE,
+                                       DirHandle,
+                                       NULL);
+
+            Status = NtOpenDirectoryObject(&BnoHandle,
+                                           DIRECTORY_QUERY |
+                                           DIRECTORY_TRAVERSE |
+                                           DIRECTORY_CREATE_OBJECT |
+                                           DIRECTORY_CREATE_SUBDIRECTORY,
+                                           &ObjectAttributes);
+            NtClose(DirHandle);
+
+        }
+    }
+
+    if (NT_SUCCESS(Status)) BaseNamedObjectDirectory = BnoHandle;
+
+Quickie:
+
+    RtlReleasePebLock();
+
+    if (Token)
+    {
+        NtSetInformationThread(NtCurrentThread(),
+                               ThreadImpersonationToken,
+                               &Token,
+                               sizeof(Token));
+
+        NtClose(Token);
+    }
+
+    return BaseNamedObjectDirectory;
+}
+
+VOID
+NTAPI
+BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry,
+                       IN PVOID Context,
+                       OUT BOOLEAN *StopEnumeration)
+{
+    /* Make sure we get Entry, Context and valid StopEnumeration pointer */
+    ASSERT(Entry);
+    ASSERT(Context);
+    ASSERT(StopEnumeration);
+
+    /* If entry is already found - signal to stop */
+    if (BasepExeLdrEntry)
+    {
+        *StopEnumeration = TRUE;
+        return;
+    }
+
+    /* Otherwise keep enumerating until we find a match */
+    if (Entry->DllBase == Context)
+    {
+        /* It matches, so remember the ldr entry */
+        BasepExeLdrEntry = Entry;
+
+        /* And stop enumeration */
+        *StopEnumeration = TRUE;
+    }
+}
+
+/*
+ * Converts an ANSI or OEM String to the TEB StaticUnicodeString
+ */
+PUNICODE_STRING
+WINAPI
+Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
+{
+    PUNICODE_STRING StaticString = &(NtCurrentTeb()->StaticUnicodeString);
+    ANSI_STRING AnsiString;
+    NTSTATUS Status;
+
+    /* Initialize an ANSI String */
+    Status = RtlInitAnsiStringEx(&AnsiString, String);
+    if (!NT_SUCCESS(Status))
+    {
+        Status = STATUS_BUFFER_OVERFLOW;
+    }
+    else
+    {
+        /* Convert it */
+        Status = Basep8BitStringToUnicodeString(StaticString, &AnsiString, FALSE);
+    }
+
+    if (NT_SUCCESS(Status)) return StaticString;
+
+    if (Status == STATUS_BUFFER_OVERFLOW)
+    {
+        SetLastError(ERROR_FILENAME_EXCED_RANGE);
+    }
+    else
+    {
+        BaseSetLastNTError(Status);
+    }
+
+    return NULL;
+}
+
+/*
+ * Allocates space from the Heap and converts an Unicode String into it
+ */
+BOOLEAN
+WINAPI
+Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString,
+                                      IN LPCSTR String)
+{
+    ANSI_STRING AnsiString;
+    NTSTATUS Status;
+
+    /* Initialize an ANSI String */
+    Status = RtlInitAnsiStringEx(&AnsiString, String);
+    if (!NT_SUCCESS(Status))
+    {
+        Status = STATUS_BUFFER_OVERFLOW;
+    }
+    else
+    {
+        /* Convert it */
+        Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, TRUE);
+    }
+
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    if (Status == STATUS_BUFFER_OVERFLOW)
+    {
+        SetLastError(ERROR_FILENAME_EXCED_RANGE);
+    }
+    else
+    {
+        BaseSetLastNTError(Status);
+    }
+
+    return FALSE;
+}
+
+/*
+ * Allocates space from the Heap and converts an Ansi String into it
+ */
+ /*NOTE: API IS A HACK */
+VOID
+WINAPI
+BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString,
+                                   OUT LPWSTR* UnicodeString)
+{
+    ANSI_STRING AnsiTemp;
+    UNICODE_STRING UnicodeTemp;
+
+    DPRINT("BasepAnsiStringToHeapUnicodeString\n");
+
+    /* First create the ANSI_STRING */
+    RtlInitAnsiString(&AnsiTemp, AnsiString);
+
+    if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp,
+                                                &AnsiTemp,
+                                                TRUE)))
+    {
+        *UnicodeString = UnicodeTemp.Buffer;
+    }
+    else
+    {
+        *UnicodeString = NULL;
+    }
+}
+
+PLARGE_INTEGER
+WINAPI
+BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout,
+                  IN DWORD dwMilliseconds)
+{
+    /* Check if this is an infinite wait, which means no timeout argument */
+    if (dwMilliseconds == INFINITE) return NULL;
+
+    /* Otherwise, convert the time to NT Format */
+    Timeout->QuadPart = dwMilliseconds * -10000LL;
+    return Timeout;
+}
+
+/*
+ * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
+ */
+POBJECT_ATTRIBUTES
+WINAPI
+BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
+                           IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL,
+                           IN PUNICODE_STRING ObjectName)
+{
+    ULONG Attributes;
+    HANDLE RootDirectory;
+    PVOID SecurityDescriptor;
+    DPRINT("BaseFormatObjectAttributes. Security: %p, Name: %p\n",
+            SecurityAttributes, ObjectName);
+
+    /* Get the attributes if present */
+    if (SecurityAttributes)
+    {
+        Attributes = SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0;
+        SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
+    }
+    else
+    {
+        if (!ObjectName) return NULL;
+        Attributes = 0;
+        SecurityDescriptor = NULL;
+    }
+
+    if (ObjectName)
+    {
+        Attributes |= OBJ_OPENIF;
+        RootDirectory = BaseGetNamedObjectDirectory();
+    }
+    else
+    {
+        RootDirectory = NULL;
+    }
+
+    /* Create the Object Attributes */
+    InitializeObjectAttributes(ObjectAttributes,
+                               ObjectName,
+                               Attributes,
+                               RootDirectory,
+                               SecurityDescriptor);
+    DPRINT("Attributes: %lx, RootDirectory: %p, SecurityDescriptor: %p\n",
+            Attributes, RootDirectory, SecurityDescriptor);
+    return ObjectAttributes;
+}
+
+/*
+ * Creates a stack for a thread or fiber
+ */
+NTSTATUS
+WINAPI
+BaseCreateStack(HANDLE hProcess,
+                 SIZE_T StackCommit,
+                 SIZE_T StackReserve,
+                 PINITIAL_TEB InitialTeb)
+{
+    NTSTATUS Status;
+    PIMAGE_NT_HEADERS Headers;
+    ULONG_PTR Stack;
+    BOOLEAN UseGuard;
+    ULONG PageSize, Dummy, AllocationGranularity;
+    SIZE_T StackReserveHeader, StackCommitHeader, GuardPageSize, GuaranteedStackCommit;
+    DPRINT("BaseCreateStack (hProcess: %p, Max: %lx, Current: %lx)\n",
+            hProcess, StackReserve, StackCommit);
+
+    /* Read page size */
+    PageSize = BaseStaticServerData->SysInfo.PageSize;
+    AllocationGranularity = BaseStaticServerData->SysInfo.AllocationGranularity;
+
+    /* Get the Image Headers */
+    Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+    if (!Headers) return STATUS_INVALID_IMAGE_FORMAT;
+
+    StackCommitHeader = Headers->OptionalHeader.SizeOfStackCommit;
+    StackReserveHeader = Headers->OptionalHeader.SizeOfStackReserve;
+
+    if (!StackReserve) StackReserve = StackReserveHeader;
+
+    if (!StackCommit)
+    {
+        StackCommit = StackCommitHeader;
+    }
+    else if (StackCommit >= StackReserve)
+    {
+        StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
+    }
+
+    StackCommit = ROUND_UP(StackCommit, PageSize);
+    StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
+
+    GuaranteedStackCommit = NtCurrentTeb()->GuaranteedStackBytes;
+    if ((GuaranteedStackCommit) && (StackCommit < GuaranteedStackCommit))
+    {
+        StackCommit = GuaranteedStackCommit;
+    }
+
+    if (StackCommit >= StackReserve)
+    {
+        StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
+    }
+
+    StackCommit = ROUND_UP(StackCommit, PageSize);
+    StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
+
+    /* Reserve memory for the stack */
+    Stack = 0;
+    Status = NtAllocateVirtualMemory(hProcess,
+                                     (PVOID*)&Stack,
+                                     0,
+                                     &StackReserve,
+                                     MEM_RESERVE,
+                                     PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failure to reserve stack: %lx\n", Status);
+        return Status;
+    }
+
+    /* Now set up some basic Initial TEB Parameters */
+    InitialTeb->AllocatedStackBase = (PVOID)Stack;
+    InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
+    InitialTeb->PreviousStackBase = NULL;
+    InitialTeb->PreviousStackLimit = NULL;
+
+    /* Update the Stack Position */
+    Stack += StackReserve - StackCommit;
+
+    /* Check if we will need a guard page */
+    if (StackReserve > StackCommit)
+    {
+        Stack -= PageSize;
+        StackCommit += PageSize;
+        UseGuard = TRUE;
+    }
+    else
+    {
+        UseGuard = FALSE;
+    }
+
+    /* Allocate memory for the stack */
+    Status = NtAllocateVirtualMemory(hProcess,
+                                     (PVOID*)&Stack,
+                                     0,
+                                     &StackCommit,
+                                     MEM_COMMIT,
+                                     PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failure to allocate stack\n");
+        GuardPageSize = 0;
+        NtFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
+        return Status;
+    }
+
+    /* Now set the current Stack Limit */
+    InitialTeb->StackLimit = (PVOID)Stack;
+
+    /* Create a guard page */
+    if (UseGuard)
+    {
+        /* Set the guard page */
+        GuardPageSize = PAGE_SIZE;
+        Status = NtProtectVirtualMemory(hProcess,
+                                        (PVOID*)&Stack,
+                                        &GuardPageSize,
+                                        PAGE_GUARD | PAGE_READWRITE,
+                                        &Dummy);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failure to set guard page\n");
+            return Status;
+        }
+
+        /* Update the Stack Limit keeping in mind the Guard Page */
+        InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
+                                         GuardPageSize);
+    }
+
+    /* We are done! */
+    return STATUS_SUCCESS;
+}
+
+VOID
+WINAPI
+BaseFreeThreadStack(IN HANDLE hProcess,
+                    IN PINITIAL_TEB InitialTeb)
+{
+    SIZE_T Dummy = 0;
+
+    /* Free the Stack */
+    NtFreeVirtualMemory(hProcess,
+                        &InitialTeb->AllocatedStackBase,
+                        &Dummy,
+                        MEM_RELEASE);
+}
+
+/*
+ * Creates the Initial Context for a Thread or Fiber
+ */
+VOID
+WINAPI
+BaseInitializeContext(IN PCONTEXT Context,
+                       IN PVOID Parameter,
+                       IN PVOID StartAddress,
+                       IN PVOID StackAddress,
+                       IN ULONG ContextType)
+{
+#ifdef _M_IX86
+    ULONG ContextFlags;
+    DPRINT("BaseInitializeContext: %p\n", Context);
+
+    /* Setup the Initial Win32 Thread Context */
+    Context->Eax = (ULONG)StartAddress;
+    Context->Ebx = (ULONG)Parameter;
+    Context->Esp = (ULONG)StackAddress;
+    /* The other registers are undefined */
+
+    /* Setup the Segments */
+    Context->SegFs = KGDT_R3_TEB;
+    Context->SegEs = KGDT_R3_DATA;
+    Context->SegDs = KGDT_R3_DATA;
+    Context->SegCs = KGDT_R3_CODE;
+    Context->SegSs = KGDT_R3_DATA;
+    Context->SegGs = 0;
+
+    /* Set the Context Flags */
+    ContextFlags = Context->ContextFlags;
+    Context->ContextFlags = CONTEXT_FULL;
+
+    /* Give it some room for the Parameter */
+    Context->Esp -= sizeof(PVOID);
+
+    /* Set the EFLAGS */
+    Context->EFlags = 0x3000; /* IOPL 3 */
+
+    /* What kind of context is being created? */
+    if (ContextType == 1)
+    {
+        /* For Threads */
+        Context->Eip = (ULONG)BaseThreadStartupThunk;
+    }
+    else if (ContextType == 2)
+    {
+        /* This is a fiber: make space for the return address */
+        Context->Esp -= sizeof(PVOID);
+        *((PVOID*)Context->Esp) = BaseFiberStartup;
+
+        /* Is FPU state required? */
+        Context->ContextFlags |= ContextFlags;
+        if (ContextFlags == CONTEXT_FLOATING_POINT)
+        {
+            /* Set an initial state */
+            Context->FloatSave.ControlWord = 0x27F;
+            Context->FloatSave.StatusWord = 0;
+            Context->FloatSave.TagWord = 0xFFFF;
+            Context->FloatSave.ErrorOffset = 0;
+            Context->FloatSave.ErrorSelector = 0;
+            Context->FloatSave.DataOffset = 0;
+            Context->FloatSave.DataSelector = 0;
+            if (SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE])
+                Context->Dr6 = 0x1F80;
+        }
+    }
+    else
+    {
+        /* For first thread in a Process */
+        Context->Eip = (ULONG)BaseProcessStartThunk;
+    }
+
+#elif defined(_M_AMD64)
+    DPRINT("BaseInitializeContext: %p\n", Context);
+
+    /* Setup the Initial Win32 Thread Context */
+    Context->Rax = (ULONG_PTR)StartAddress;
+    Context->Rbx = (ULONG_PTR)Parameter;
+    Context->Rsp = (ULONG_PTR)StackAddress;
+    /* The other registers are undefined */
+
+    /* Setup the Segments */
+    Context->SegGs = KGDT64_R3_DATA | RPL_MASK;
+    Context->SegEs = KGDT64_R3_DATA | RPL_MASK;
+    Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
+    Context->SegCs = KGDT64_R3_CODE | RPL_MASK;
+    Context->SegSs = KGDT64_R3_DATA | RPL_MASK;
+    Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
+
+    /* Set the EFLAGS */
+    Context->EFlags = 0x3000; /* IOPL 3 */
+
+    if (ContextType == 1)      /* For Threads */
+    {
+        Context->Rip = (ULONG_PTR)BaseThreadStartupThunk;
+    }
+    else if (ContextType == 2) /* For Fibers */
+    {
+        Context->Rip = (ULONG_PTR)BaseFiberStartup;
+    }
+    else                       /* For first thread in a Process */
+    {
+        Context->Rip = (ULONG_PTR)BaseProcessStartThunk;
+    }
+
+    /* Set the Context Flags */
+    Context->ContextFlags = CONTEXT_FULL;
+
+    /* Give it some room for the Parameter */
+    Context->Rsp -= sizeof(PVOID);
+#else
+#warning Unknown architecture
+    UNIMPLEMENTED;
+    DbgBreakPoint();
+#endif
+}
+
+/*
+ * Checks if the privilege for Real-Time Priority is there
+ * Beware about this function behavior:
+ * - In case Keep is set to FALSE, then the function will only check
+ * whether real time is allowed and won't grant the privilege. In that case
+ * it will return TRUE if allowed, FALSE otherwise. Not a state!
+ * It means you don't have to release privilege when calling with FALSE.
+ */
+PVOID
+WINAPI
+BasepIsRealtimeAllowed(IN BOOLEAN Keep)
+{
+    ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
+    PVOID State;
+    NTSTATUS Status;
+
+    Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
+    if (!NT_SUCCESS(Status)) return NULL;
+
+    if (!Keep)
+    {
+        RtlReleasePrivilege(State);
+        State = (PVOID)TRUE;
+    }
+
+    return State;
+}
+
+/*
+ * Maps an image file into a section
+ */
+NTSTATUS
+WINAPI
+BasepMapFile(IN LPCWSTR lpApplicationName,
+             OUT PHANDLE hSection,
+             IN PUNICODE_STRING ApplicationName)
+{
+    RTL_RELATIVE_NAME_U RelativeName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE hFile = NULL;
+    IO_STATUS_BLOCK IoStatusBlock;
+
+    DPRINT("BasepMapFile\n");
+
+    /* Zero out the Relative Directory */
+    RelativeName.ContainingDirectory = NULL;
+
+    /* Find the application name */
+    if (!RtlDosPathNameToNtPathName_U(lpApplicationName,
+                                      ApplicationName,
+                                      NULL,
+                                      &RelativeName))
+    {
+        return STATUS_OBJECT_PATH_NOT_FOUND;
+    }
+
+    DPRINT("ApplicationName %wZ\n", ApplicationName);
+    DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName);
+
+    /* Did we get a relative name? */
+    if (RelativeName.RelativeName.Length)
+    {
+        ApplicationName = &RelativeName.RelativeName;
+    }
+
+    /* Initialize the Object Attributes */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               ApplicationName,
+                               OBJ_CASE_INSENSITIVE,
+                               RelativeName.ContainingDirectory,
+                               NULL);
+
+    /* Try to open the executable */
+    Status = NtOpenFile(&hFile,
+                        SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_DELETE | FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to open file\n");
+        BaseSetLastNTError(Status);
+        return Status;
+    }
+
+    /* Create a section for this file */
+    Status = NtCreateSection(hSection,
+                             SECTION_ALL_ACCESS,
+                             NULL,
+                             NULL,
+                             PAGE_EXECUTE,
+                             SEC_IMAGE,
+                             hFile);
+    NtClose(hFile);
+
+    /* Return status */
+    DPRINT("Section: %p for file: %p\n", *hSection, hFile);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+WINAPI
+Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection)
+{
+    NTSTATUS Status;
+    BOOL Result;
+
+    Status = RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection);
+    if (NT_SUCCESS(Status))
+    {
+        Result = TRUE;
+    }
+    else
+    {
+        BaseSetLastNTError(Status);
+        Result = FALSE;
+    }
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+Wow64DisableWow64FsRedirection(IN PVOID *OldValue)
+{
+    NTSTATUS Status;
+    BOOL Result;
+
+    Status = RtlWow64EnableFsRedirectionEx((PVOID)TRUE, OldValue);
+    if (NT_SUCCESS(Status))
+    {
+        Result = TRUE;
+    }
+    else
+    {
+        BaseSetLastNTError(Status);
+        Result = FALSE;
+    }
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+Wow64RevertWow64FsRedirection(IN PVOID OldValue)
+{
+    NTSTATUS Status;
+    BOOL Result;
+
+    Status = RtlWow64EnableFsRedirectionEx(OldValue, &OldValue);
+    if (NT_SUCCESS(Status))
+    {
+        Result = TRUE;
+    }
+    else
+    {
+        BaseSetLastNTError(Status);
+        Result = FALSE;
+    }
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+SetFileApisToOEM(VOID)
+{
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
+    BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
+    BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
+    Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+SetFileApisToANSI(VOID)
+{
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
+    BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
+    BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
+    Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+AreFileApisANSI(VOID)
+{
+   return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+BaseMarkFileForDelete(IN HANDLE FileHandle,
+                      IN ULONG FileAttributes)
+{
+    IO_STATUS_BLOCK IoStatusBlock;
+    FILE_BASIC_INFORMATION FileBasicInfo;
+    FILE_DISPOSITION_INFORMATION FileDispositionInfo;
+
+    /* If no attributes were given, get them */
+    if (!FileAttributes)
+    {
+        FileBasicInfo.FileAttributes = 0;
+        NtQueryInformationFile(FileHandle,
+                               &IoStatusBlock,
+                               &FileBasicInfo,
+                               sizeof(FileBasicInfo),
+                               FileBasicInformation);
+        FileAttributes = FileBasicInfo.FileAttributes;
+    }
+
+    /* If file is marked as RO, reset its attributes */
+    if (FileAttributes & FILE_ATTRIBUTE_READONLY)
+    {
+        RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
+        FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+        NtSetInformationFile(FileHandle,
+                             &IoStatusBlock,
+                             &FileBasicInfo,
+                             sizeof(FileBasicInfo),
+                             FileBasicInformation);
+    }
+
+    /* Finally, mark the file for deletion */
+    FileDispositionInfo.DeleteFile = TRUE;
+    NtSetInformationFile(FileHandle,
+                         &IoStatusBlock,
+                         &FileDispositionInfo,
+                         sizeof(FileDispositionInfo),
+                         FileDispositionInformation);
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+BaseCheckRunApp(IN DWORD Unknown1,
+                IN DWORD Unknown2,
+                IN DWORD Unknown3,
+                IN DWORD Unknown4,
+                IN DWORD Unknown5,
+                IN DWORD Unknown6,
+                IN DWORD Unknown7,
+                IN DWORD Unknown8,
+                IN DWORD Unknown9,
+                IN DWORD Unknown10)
+{
+    STUB;
+    return FALSE;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+WINAPI
+BasepCheckWinSaferRestrictions(IN HANDLE UserToken,
+                               IN LPWSTR ApplicationName,
+                               IN HANDLE FileHandle,
+                               OUT PBOOLEAN InJob,
+                               OUT PHANDLE NewToken,
+                               OUT PHANDLE JobHandle)
+{
+    NTSTATUS Status;
+    
+    /* Validate that there's a name */
+    if ((ApplicationName) && *(ApplicationName))
+    {
+        /* Validate that the required output parameters are there */
+        if ((InJob) && (NewToken) && (JobHandle))
+        {
+            /* Do the work (one day...) */
+            UNIMPLEMENTED;
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            /* Act as if SEH hit this */
+            Status = STATUS_ACCESS_VIOLATION;
+        }
+    }
+    else
+    {
+        /* Input is invalid */
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    /* Return the status */
+    return Status;
+}