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