xref: /reactos/dll/win32/kernel32/client/utils.c (revision 60eea2d7)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            lib/kernel32/misc/utils.c
5  * PURPOSE:         Utility and Support Functions
6  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
7  *                  Pierre Schweitzer (pierre.schweitzer@reactos.org)
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <k32.h>
13 #ifdef _M_IX86
14 #include "i386/ketypes.h"
15 #elif defined _M_AMD64
16 #include "amd64/ketypes.h"
17 #endif
18 
19 #define NDEBUG
20 #include <debug.h>
21 
22 /* GLOBALS ********************************************************************/
23 
24 UNICODE_STRING Restricted = RTL_CONSTANT_STRING(L"Restricted");
25 BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
26 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
27 PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
28 PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
29 PRTL_COUNT_STRINGA Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
30 
31 /* FUNCTIONS ******************************************************************/
32 
33 ULONG
34 NTAPI
35 BasepUnicodeStringToOemSize(IN PUNICODE_STRING String)
36 {
37     return RtlUnicodeStringToOemSize(String);
38 }
39 
40 ULONG
41 NTAPI
42 BasepOemStringToUnicodeSize(IN PANSI_STRING String)
43 {
44     return RtlOemStringToUnicodeSize(String);
45 }
46 
47 ULONG
48 NTAPI
49 BasepUnicodeStringToAnsiSize(IN PUNICODE_STRING String)
50 {
51     return RtlUnicodeStringToAnsiSize(String);
52 }
53 
54 ULONG
55 NTAPI
56 BasepAnsiStringToUnicodeSize(IN PANSI_STRING String)
57 {
58     return RtlAnsiStringToUnicodeSize(String);
59 }
60 
61 HANDLE
62 WINAPI
63 BaseGetNamedObjectDirectory(VOID)
64 {
65     OBJECT_ATTRIBUTES ObjectAttributes;
66     NTSTATUS Status;
67     HANDLE DirHandle, BnoHandle, Token, NewToken;
68 
69     if (BaseNamedObjectDirectory) return BaseNamedObjectDirectory;
70 
71     if (NtCurrentTeb()->IsImpersonating)
72     {
73         Status = NtOpenThreadToken(NtCurrentThread(),
74                                    TOKEN_IMPERSONATE,
75                                    TRUE,
76                                    &Token);
77         if (!NT_SUCCESS(Status)) return BaseNamedObjectDirectory;
78 
79         NewToken = NULL;
80         Status = NtSetInformationThread(NtCurrentThread(),
81                                         ThreadImpersonationToken,
82                                         &NewToken,
83                                         sizeof(HANDLE));
84         if (!NT_SUCCESS (Status))
85         {
86             NtClose(Token);
87             return BaseNamedObjectDirectory;
88         }
89     }
90     else
91     {
92         Token = NULL;
93     }
94 
95     RtlAcquirePebLock();
96     if (BaseNamedObjectDirectory) goto Quickie;
97 
98     InitializeObjectAttributes(&ObjectAttributes,
99                                &BaseStaticServerData->NamedObjectDirectory,
100                                OBJ_CASE_INSENSITIVE,
101                                NULL,
102                                NULL);
103 
104     Status = NtOpenDirectoryObject(&BnoHandle,
105                                    DIRECTORY_QUERY |
106                                    DIRECTORY_TRAVERSE |
107                                    DIRECTORY_CREATE_OBJECT |
108                                    DIRECTORY_CREATE_SUBDIRECTORY,
109                                    &ObjectAttributes);
110     if (!NT_SUCCESS(Status))
111     {
112         Status = NtOpenDirectoryObject(&DirHandle,
113                                        DIRECTORY_TRAVERSE,
114                                        &ObjectAttributes);
115 
116         if (NT_SUCCESS(Status))
117         {
118             InitializeObjectAttributes(&ObjectAttributes,
119                                        (PUNICODE_STRING)&Restricted,
120                                        OBJ_CASE_INSENSITIVE,
121                                        DirHandle,
122                                        NULL);
123 
124             Status = NtOpenDirectoryObject(&BnoHandle,
125                                            DIRECTORY_QUERY |
126                                            DIRECTORY_TRAVERSE |
127                                            DIRECTORY_CREATE_OBJECT |
128                                            DIRECTORY_CREATE_SUBDIRECTORY,
129                                            &ObjectAttributes);
130             NtClose(DirHandle);
131 
132         }
133     }
134 
135     if (NT_SUCCESS(Status)) BaseNamedObjectDirectory = BnoHandle;
136 
137 Quickie:
138 
139     RtlReleasePebLock();
140 
141     if (Token)
142     {
143         NtSetInformationThread(NtCurrentThread(),
144                                ThreadImpersonationToken,
145                                &Token,
146                                sizeof(Token));
147 
148         NtClose(Token);
149     }
150 
151     return BaseNamedObjectDirectory;
152 }
153 
154 VOID
155 NTAPI
156 BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry,
157                        IN PVOID Context,
158                        OUT BOOLEAN *StopEnumeration)
159 {
160     /* Make sure we get Entry, Context and valid StopEnumeration pointer */
161     ASSERT(Entry);
162     ASSERT(Context);
163     ASSERT(StopEnumeration);
164 
165     /* If entry is already found - signal to stop */
166     if (BasepExeLdrEntry)
167     {
168         *StopEnumeration = TRUE;
169         return;
170     }
171 
172     /* Otherwise keep enumerating until we find a match */
173     if (Entry->DllBase == Context)
174     {
175         /* It matches, so remember the ldr entry */
176         BasepExeLdrEntry = Entry;
177 
178         /* And stop enumeration */
179         *StopEnumeration = TRUE;
180     }
181 }
182 
183 /*
184  * Converts an ANSI or OEM String to the TEB StaticUnicodeString
185  */
186 PUNICODE_STRING
187 WINAPI
188 Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
189 {
190     PUNICODE_STRING StaticString = &(NtCurrentTeb()->StaticUnicodeString);
191     ANSI_STRING AnsiString;
192     NTSTATUS Status;
193 
194     /* Initialize an ANSI String */
195     Status = RtlInitAnsiStringEx(&AnsiString, String);
196     if (!NT_SUCCESS(Status))
197     {
198         Status = STATUS_BUFFER_OVERFLOW;
199     }
200     else
201     {
202         /* Convert it */
203         Status = Basep8BitStringToUnicodeString(StaticString, &AnsiString, FALSE);
204     }
205 
206     if (NT_SUCCESS(Status)) return StaticString;
207 
208     if (Status == STATUS_BUFFER_OVERFLOW)
209     {
210         SetLastError(ERROR_FILENAME_EXCED_RANGE);
211     }
212     else
213     {
214         BaseSetLastNTError(Status);
215     }
216 
217     return NULL;
218 }
219 
220 /*
221  * Allocates space from the Heap and converts an Unicode String into it
222  */
223 BOOLEAN
224 WINAPI
225 Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString,
226                                       IN LPCSTR String)
227 {
228     ANSI_STRING AnsiString;
229     NTSTATUS Status;
230 
231     /* Initialize an ANSI String */
232     Status = RtlInitAnsiStringEx(&AnsiString, String);
233     if (!NT_SUCCESS(Status))
234     {
235         Status = STATUS_BUFFER_OVERFLOW;
236     }
237     else
238     {
239         /* Convert it */
240         Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, TRUE);
241     }
242 
243     if (NT_SUCCESS(Status)) return TRUE;
244 
245     if (Status == STATUS_BUFFER_OVERFLOW)
246     {
247         SetLastError(ERROR_FILENAME_EXCED_RANGE);
248     }
249     else
250     {
251         BaseSetLastNTError(Status);
252     }
253 
254     return FALSE;
255 }
256 
257 /*
258  * Allocates space from the Heap and converts an Ansi String into it
259  */
260  /*NOTE: API IS A HACK */
261 VOID
262 WINAPI
263 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString,
264                                    OUT LPWSTR* UnicodeString)
265 {
266     ANSI_STRING AnsiTemp;
267     UNICODE_STRING UnicodeTemp;
268 
269     DPRINT("BasepAnsiStringToHeapUnicodeString\n");
270 
271     /* First create the ANSI_STRING */
272     RtlInitAnsiString(&AnsiTemp, AnsiString);
273 
274     if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp,
275                                                 &AnsiTemp,
276                                                 TRUE)))
277     {
278         *UnicodeString = UnicodeTemp.Buffer;
279     }
280     else
281     {
282         *UnicodeString = NULL;
283     }
284 }
285 
286 PLARGE_INTEGER
287 WINAPI
288 BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout,
289                   IN DWORD dwMilliseconds)
290 {
291     /* Check if this is an infinite wait, which means no timeout argument */
292     if (dwMilliseconds == INFINITE) return NULL;
293 
294     /* Otherwise, convert the time to NT Format */
295     Timeout->QuadPart = UInt32x32To64(dwMilliseconds, -10000);
296     return Timeout;
297 }
298 
299 /*
300  * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
301  */
302 POBJECT_ATTRIBUTES
303 WINAPI
304 BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
305                            IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL,
306                            IN PUNICODE_STRING ObjectName)
307 {
308     ULONG Attributes;
309     HANDLE RootDirectory;
310     PVOID SecurityDescriptor;
311     DPRINT("BaseFormatObjectAttributes. Security: %p, Name: %p\n",
312             SecurityAttributes, ObjectName);
313 
314     /* Get the attributes if present */
315     if (SecurityAttributes)
316     {
317         Attributes = SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0;
318         SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
319     }
320     else
321     {
322         if (!ObjectName) return NULL;
323         Attributes = 0;
324         SecurityDescriptor = NULL;
325     }
326 
327     if (ObjectName)
328     {
329         Attributes |= OBJ_OPENIF;
330         RootDirectory = BaseGetNamedObjectDirectory();
331     }
332     else
333     {
334         RootDirectory = NULL;
335     }
336 
337     /* Create the Object Attributes */
338     InitializeObjectAttributes(ObjectAttributes,
339                                ObjectName,
340                                Attributes,
341                                RootDirectory,
342                                SecurityDescriptor);
343     DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
344             Attributes, RootDirectory, SecurityDescriptor);
345     return ObjectAttributes;
346 }
347 
348 /*
349  * Creates a stack for a thread or fiber
350  */
351 NTSTATUS
352 WINAPI
353 BaseCreateStack(HANDLE hProcess,
354                  SIZE_T StackReserve,
355                  SIZE_T StackCommit,
356                  PINITIAL_TEB InitialTeb)
357 {
358     NTSTATUS Status;
359     PIMAGE_NT_HEADERS Headers;
360     ULONG_PTR Stack;
361     BOOLEAN UseGuard;
362     ULONG PageSize, Dummy, AllocationGranularity;
363     SIZE_T StackReserveHeader, StackCommitHeader, GuardPageSize, GuaranteedStackCommit;
364     DPRINT("BaseCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
365             hProcess, StackReserve, StackCommit);
366 
367     /* Read page size */
368     PageSize = BaseStaticServerData->SysInfo.PageSize;
369     AllocationGranularity = BaseStaticServerData->SysInfo.AllocationGranularity;
370 
371     /* Get the Image Headers */
372     Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
373     if (!Headers) return STATUS_INVALID_IMAGE_FORMAT;
374 
375     StackCommitHeader = Headers->OptionalHeader.SizeOfStackCommit;
376     StackReserveHeader = Headers->OptionalHeader.SizeOfStackReserve;
377 
378     if (!StackReserve) StackReserve = StackReserveHeader;
379 
380     if (!StackCommit)
381     {
382         StackCommit = StackCommitHeader;
383     }
384     else if (StackCommit >= StackReserve)
385     {
386         StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
387     }
388 
389     StackCommit = ROUND_UP(StackCommit, PageSize);
390     StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
391 
392     GuaranteedStackCommit = NtCurrentTeb()->GuaranteedStackBytes;
393     if ((GuaranteedStackCommit) && (StackCommit < GuaranteedStackCommit))
394     {
395         StackCommit = GuaranteedStackCommit;
396     }
397 
398     if (StackCommit >= StackReserve)
399     {
400         StackReserve = ROUND_UP(StackCommit, 1024 * 1024);
401     }
402 
403     StackCommit = ROUND_UP(StackCommit, PageSize);
404     StackReserve = ROUND_UP(StackReserve, AllocationGranularity);
405 
406     /* ROS Hack until we support guard page stack expansion */
407     StackCommit = StackReserve;
408 
409     /* Reserve memory for the stack */
410     Stack = 0;
411     Status = ZwAllocateVirtualMemory(hProcess,
412                                      (PVOID*)&Stack,
413                                      0,
414                                      &StackReserve,
415                                      MEM_RESERVE,
416                                      PAGE_READWRITE);
417     if (!NT_SUCCESS(Status))
418     {
419         DPRINT1("Failure to reserve stack: %lx\n", Status);
420         return Status;
421     }
422 
423     /* Now set up some basic Initial TEB Parameters */
424     InitialTeb->AllocatedStackBase = (PVOID)Stack;
425     InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
426     InitialTeb->PreviousStackBase = NULL;
427     InitialTeb->PreviousStackLimit = NULL;
428 
429     /* Update the Stack Position */
430     Stack += StackReserve - StackCommit;
431 
432     /* Check if we will need a guard page */
433     if (StackReserve > StackCommit)
434     {
435         Stack -= PageSize;
436         StackCommit += PageSize;
437         UseGuard = TRUE;
438     }
439     else
440     {
441         UseGuard = FALSE;
442     }
443 
444     /* Allocate memory for the stack */
445     Status = ZwAllocateVirtualMemory(hProcess,
446                                      (PVOID*)&Stack,
447                                      0,
448                                      &StackCommit,
449                                      MEM_COMMIT,
450                                      PAGE_READWRITE);
451     if (!NT_SUCCESS(Status))
452     {
453         DPRINT1("Failure to allocate stack\n");
454         GuardPageSize = 0;
455         ZwFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
456         return Status;
457     }
458 
459     /* Now set the current Stack Limit */
460     InitialTeb->StackLimit = (PVOID)Stack;
461 
462     /* Create a guard page */
463     if (UseGuard)
464     {
465         /* Set the guard page */
466         GuardPageSize = PAGE_SIZE;
467         Status = ZwProtectVirtualMemory(hProcess,
468                                         (PVOID*)&Stack,
469                                         &GuardPageSize,
470                                         PAGE_GUARD | PAGE_READWRITE,
471                                         &Dummy);
472         if (!NT_SUCCESS(Status))
473         {
474             DPRINT1("Failure to set guard page\n");
475             return Status;
476         }
477 
478         /* Update the Stack Limit keeping in mind the Guard Page */
479         InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
480                                          GuardPageSize);
481     }
482 
483     /* We are done! */
484     return STATUS_SUCCESS;
485 }
486 
487 VOID
488 WINAPI
489 BaseFreeThreadStack(IN HANDLE hProcess,
490                     IN PINITIAL_TEB InitialTeb)
491 {
492     SIZE_T Dummy = 0;
493 
494     /* Free the Stack */
495     NtFreeVirtualMemory(hProcess,
496                         &InitialTeb->AllocatedStackBase,
497                         &Dummy,
498                         MEM_RELEASE);
499 }
500 
501 /*
502  * Creates the Initial Context for a Thread or Fiber
503  */
504 VOID
505 WINAPI
506 BaseInitializeContext(IN PCONTEXT Context,
507                        IN PVOID Parameter,
508                        IN PVOID StartAddress,
509                        IN PVOID StackAddress,
510                        IN ULONG ContextType)
511 {
512 #ifdef _M_IX86
513     ULONG ContextFlags;
514     DPRINT("BaseInitializeContext: %p\n", Context);
515 
516     /* Setup the Initial Win32 Thread Context */
517     Context->Eax = (ULONG)StartAddress;
518     Context->Ebx = (ULONG)Parameter;
519     Context->Esp = (ULONG)StackAddress;
520     /* The other registers are undefined */
521 
522     /* Setup the Segments */
523     Context->SegFs = KGDT_R3_TEB;
524     Context->SegEs = KGDT_R3_DATA;
525     Context->SegDs = KGDT_R3_DATA;
526     Context->SegCs = KGDT_R3_CODE;
527     Context->SegSs = KGDT_R3_DATA;
528     Context->SegGs = 0;
529 
530     /* Set the Context Flags */
531     ContextFlags = Context->ContextFlags;
532     Context->ContextFlags = CONTEXT_FULL;
533 
534     /* Give it some room for the Parameter */
535     Context->Esp -= sizeof(PVOID);
536 
537     /* Set the EFLAGS */
538     Context->EFlags = 0x3000; /* IOPL 3 */
539 
540     /* What kind of context is being created? */
541     if (ContextType == 1)
542     {
543         /* For Threads */
544         Context->Eip = (ULONG)BaseThreadStartupThunk;
545     }
546     else if (ContextType == 2)
547     {
548         /* This is a fiber: make space for the return address */
549         Context->Esp -= sizeof(PVOID);
550         *((PVOID*)Context->Esp) = BaseFiberStartup;
551 
552         /* Is FPU state required? */
553         Context->ContextFlags |= ContextFlags;
554         if (ContextFlags == CONTEXT_FLOATING_POINT)
555         {
556             /* Set an initial state */
557             Context->FloatSave.ControlWord = 0x27F;
558             Context->FloatSave.StatusWord = 0;
559             Context->FloatSave.TagWord = 0xFFFF;
560             Context->FloatSave.ErrorOffset = 0;
561             Context->FloatSave.ErrorSelector = 0;
562             Context->FloatSave.DataOffset = 0;
563             Context->FloatSave.DataSelector = 0;
564             if (SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE])
565                 Context->Dr6 = 0x1F80;
566         }
567     }
568     else
569     {
570         /* For first thread in a Process */
571         Context->Eip = (ULONG)BaseProcessStartThunk;
572     }
573 
574 #elif defined(_M_AMD64)
575     DPRINT("BaseInitializeContext: %p\n", Context);
576 
577     /* Setup the Initial Win32 Thread Context */
578     Context->Rax = (ULONG_PTR)StartAddress;
579     Context->Rbx = (ULONG_PTR)Parameter;
580     Context->Rsp = (ULONG_PTR)StackAddress;
581     /* The other registers are undefined */
582 
583     /* Setup the Segments */
584     Context->SegGs = KGDT64_R3_DATA | RPL_MASK;
585     Context->SegEs = KGDT64_R3_DATA | RPL_MASK;
586     Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
587     Context->SegCs = KGDT64_R3_CODE | RPL_MASK;
588     Context->SegSs = KGDT64_R3_DATA | RPL_MASK;
589     Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
590 
591     /* Set the EFLAGS */
592     Context->EFlags = 0x3000; /* IOPL 3 */
593 
594     if (ContextType == 1)      /* For Threads */
595     {
596         Context->Rip = (ULONG_PTR)BaseThreadStartupThunk;
597     }
598     else if (ContextType == 2) /* For Fibers */
599     {
600         Context->Rip = (ULONG_PTR)BaseFiberStartup;
601     }
602     else                       /* For first thread in a Process */
603     {
604         Context->Rip = (ULONG_PTR)BaseProcessStartThunk;
605     }
606 
607     /* Set the Context Flags */
608     Context->ContextFlags = CONTEXT_FULL;
609 
610     /* Give it some room for the Parameter */
611     Context->Rsp -= sizeof(PVOID);
612 #else
613 #warning Unknown architecture
614     UNIMPLEMENTED;
615     DbgBreakPoint();
616 #endif
617 }
618 
619 /*
620  * Checks if the privilege for Real-Time Priority is there
621  */
622 PVOID
623 WINAPI
624 BasepIsRealtimeAllowed(IN BOOLEAN Keep)
625 {
626     ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
627     PVOID State;
628     NTSTATUS Status;
629 
630     Status = RtlAcquirePrivilege(&Privilege, TRUE, FALSE, &State);
631     if (!NT_SUCCESS(Status)) return NULL;
632 
633     if (Keep)
634     {
635         RtlReleasePrivilege(State);
636         State = (PVOID)TRUE;
637     }
638 
639     return State;
640 }
641 
642 /*
643  * Maps an image file into a section
644  */
645 NTSTATUS
646 WINAPI
647 BasepMapFile(IN LPCWSTR lpApplicationName,
648              OUT PHANDLE hSection,
649              IN PUNICODE_STRING ApplicationName)
650 {
651     RTL_RELATIVE_NAME_U RelativeName;
652     OBJECT_ATTRIBUTES ObjectAttributes;
653     NTSTATUS Status;
654     HANDLE hFile = NULL;
655     IO_STATUS_BLOCK IoStatusBlock;
656 
657     DPRINT("BasepMapFile\n");
658 
659     /* Zero out the Relative Directory */
660     RelativeName.ContainingDirectory = NULL;
661 
662     /* Find the application name */
663     if (!RtlDosPathNameToNtPathName_U(lpApplicationName,
664                                       ApplicationName,
665                                       NULL,
666                                       &RelativeName))
667     {
668         return STATUS_OBJECT_PATH_NOT_FOUND;
669     }
670 
671     DPRINT("ApplicationName %wZ\n", ApplicationName);
672     DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName);
673 
674     /* Did we get a relative name? */
675     if (RelativeName.RelativeName.Length)
676     {
677         ApplicationName = &RelativeName.RelativeName;
678     }
679 
680     /* Initialize the Object Attributes */
681     InitializeObjectAttributes(&ObjectAttributes,
682                                ApplicationName,
683                                OBJ_CASE_INSENSITIVE,
684                                RelativeName.ContainingDirectory,
685                                NULL);
686 
687     /* Try to open the executable */
688     Status = NtOpenFile(&hFile,
689                         SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
690                         &ObjectAttributes,
691                         &IoStatusBlock,
692                         FILE_SHARE_DELETE | FILE_SHARE_READ,
693                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
694     if (!NT_SUCCESS(Status))
695     {
696         DPRINT1("Failed to open file\n");
697         BaseSetLastNTError(Status);
698         return Status;
699     }
700 
701     /* Create a section for this file */
702     Status = NtCreateSection(hSection,
703                              SECTION_ALL_ACCESS,
704                              NULL,
705                              NULL,
706                              PAGE_EXECUTE,
707                              SEC_IMAGE,
708                              hFile);
709     NtClose(hFile);
710 
711     /* Return status */
712     DPRINT("Section: %lx for file: %lx\n", *hSection, hFile);
713     return Status;
714 }
715 
716 /*
717  * @implemented
718  */
719 BOOLEAN
720 WINAPI
721 Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection)
722 {
723     NTSTATUS Status;
724     BOOL Result;
725 
726     Status = RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection);
727     if (NT_SUCCESS(Status))
728     {
729         Result = TRUE;
730     }
731     else
732     {
733         BaseSetLastNTError(Status);
734         Result = FALSE;
735     }
736     return Result;
737 }
738 
739 /*
740  * @implemented
741  */
742 BOOL
743 WINAPI
744 Wow64DisableWow64FsRedirection(IN PVOID *OldValue)
745 {
746     NTSTATUS Status;
747     BOOL Result;
748 
749     Status = RtlWow64EnableFsRedirectionEx((PVOID)TRUE, OldValue);
750     if (NT_SUCCESS(Status))
751     {
752         Result = TRUE;
753     }
754     else
755     {
756         BaseSetLastNTError(Status);
757         Result = FALSE;
758     }
759     return Result;
760 }
761 
762 /*
763  * @implemented
764  */
765 BOOL
766 WINAPI
767 Wow64RevertWow64FsRedirection(IN PVOID OldValue)
768 {
769     NTSTATUS Status;
770     BOOL Result;
771 
772     Status = RtlWow64EnableFsRedirectionEx(OldValue, &OldValue);
773     if (NT_SUCCESS(Status))
774     {
775         Result = TRUE;
776     }
777     else
778     {
779         BaseSetLastNTError(Status);
780         Result = FALSE;
781     }
782     return Result;
783 }
784 
785 /*
786  * @implemented
787  */
788 VOID
789 WINAPI
790 SetFileApisToOEM(VOID)
791 {
792     /* Set the correct Base Api */
793     Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
794     BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
795     BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
796     Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
797 
798     /* FIXME: Old, deprecated way */
799     bIsFileApiAnsi = FALSE;
800 }
801 
802 
803 /*
804  * @implemented
805  */
806 VOID
807 WINAPI
808 SetFileApisToANSI(VOID)
809 {
810     /* Set the correct Base Api */
811     Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
812     BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
813     BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
814     Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
815 
816     /* FIXME: Old, deprecated way */
817     bIsFileApiAnsi = TRUE;
818 }
819 
820 /*
821  * @implemented
822  */
823 BOOL
824 WINAPI
825 AreFileApisANSI(VOID)
826 {
827    return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
828 }
829 
830 /*
831  * @implemented
832  */
833 VOID
834 WINAPI
835 BaseMarkFileForDelete(IN HANDLE FileHandle,
836                       IN ULONG FileAttributes)
837 {
838     IO_STATUS_BLOCK IoStatusBlock;
839     FILE_BASIC_INFORMATION FileBasicInfo;
840     FILE_DISPOSITION_INFORMATION FileDispositionInfo;
841 
842     /* If no attributes were given, get them */
843     if (!FileAttributes)
844     {
845         FileBasicInfo.FileAttributes = 0;
846         NtQueryInformationFile(FileHandle,
847                                &IoStatusBlock,
848                                &FileBasicInfo,
849                                sizeof(FileBasicInfo),
850                                FileBasicInformation);
851         FileAttributes = FileBasicInfo.FileAttributes;
852     }
853 
854     /* If file is marked as RO, reset its attributes */
855     if (FileAttributes & FILE_ATTRIBUTE_READONLY)
856     {
857         RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
858         FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
859         NtSetInformationFile(FileHandle,
860                              &IoStatusBlock,
861                              &FileBasicInfo,
862                              sizeof(FileBasicInfo),
863                              FileBasicInformation);
864     }
865 
866     /* Finally, mark the file for deletion */
867     FileDispositionInfo.DeleteFile = TRUE;
868     NtSetInformationFile(FileHandle,
869                          &IoStatusBlock,
870                          &FileDispositionInfo,
871                          sizeof(FileDispositionInfo),
872                          FileDispositionInformation);
873 }
874 
875 /*
876  * @unimplemented
877  */
878 BOOL
879 WINAPI
880 BaseCheckRunApp(IN DWORD Unknown1,
881                 IN DWORD Unknown2,
882                 IN DWORD Unknown3,
883                 IN DWORD Unknown4,
884                 IN DWORD Unknown5,
885                 IN DWORD Unknown6,
886                 IN DWORD Unknown7,
887                 IN DWORD Unknown8,
888                 IN DWORD Unknown9,
889                 IN DWORD Unknown10)
890 {
891     STUB;
892     return FALSE;
893 }
894 
895 /*
896  * @unimplemented
897  */
898 NTSTATUS
899 WINAPI
900 BasepCheckWinSaferRestrictions(IN HANDLE UserToken,
901                                IN LPWSTR ApplicationName,
902                                IN HANDLE FileHandle,
903                                OUT PBOOLEAN InJob,
904                                OUT PHANDLE NewToken,
905                                OUT PHANDLE JobHandle)
906 {
907     NTSTATUS Status;
908 
909     /* Validate that there's a name */
910     if ((ApplicationName) && *(ApplicationName))
911     {
912         /* Validate that the required output parameters are there */
913         if ((InJob) && (NewToken) && (JobHandle))
914         {
915             /* Do the work (one day...) */
916             UNIMPLEMENTED;
917             Status = STATUS_SUCCESS;
918         }
919         else
920         {
921             /* Act as if SEH hit this */
922             Status = STATUS_ACCESS_VIOLATION;
923         }
924     }
925     else
926     {
927         /* Input is invalid */
928         Status = STATUS_INVALID_PARAMETER;
929     }
930 
931     /* Return the status */
932     return Status;
933 }
934