Merge my current work done on the kd++ branch:
[reactos.git] / reactos / dll / win32 / kernel32 / client / utils.c
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 = NtAllocateVirtualMemory(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 = NtAllocateVirtualMemory(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 NtFreeVirtualMemory(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 = NtProtectVirtualMemory(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, 1, 0, &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 }