e0654c9700cce4a520f195175a00c9badd5acbe6
[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: 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
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 = dwMilliseconds * -10000LL;
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: %p, 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 StackCommit,
355 SIZE_T StackReserve,
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: %p, 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 /* Reserve memory for the stack */
407 Stack = 0;
408 Status = NtAllocateVirtualMemory(hProcess,
409 (PVOID*)&Stack,
410 0,
411 &StackReserve,
412 MEM_RESERVE,
413 PAGE_READWRITE);
414 if (!NT_SUCCESS(Status))
415 {
416 DPRINT1("Failure to reserve stack: %lx\n", Status);
417 return Status;
418 }
419
420 /* Now set up some basic Initial TEB Parameters */
421 InitialTeb->AllocatedStackBase = (PVOID)Stack;
422 InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
423 InitialTeb->PreviousStackBase = NULL;
424 InitialTeb->PreviousStackLimit = NULL;
425
426 /* Update the Stack Position */
427 Stack += StackReserve - StackCommit;
428
429 /* Check if we will need a guard page */
430 if (StackReserve > StackCommit)
431 {
432 Stack -= PageSize;
433 StackCommit += PageSize;
434 UseGuard = TRUE;
435 }
436 else
437 {
438 UseGuard = FALSE;
439 }
440
441 /* Allocate memory for the stack */
442 Status = NtAllocateVirtualMemory(hProcess,
443 (PVOID*)&Stack,
444 0,
445 &StackCommit,
446 MEM_COMMIT,
447 PAGE_READWRITE);
448 if (!NT_SUCCESS(Status))
449 {
450 DPRINT1("Failure to allocate stack\n");
451 GuardPageSize = 0;
452 NtFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE);
453 return Status;
454 }
455
456 /* Now set the current Stack Limit */
457 InitialTeb->StackLimit = (PVOID)Stack;
458
459 /* Create a guard page */
460 if (UseGuard)
461 {
462 /* Set the guard page */
463 GuardPageSize = PAGE_SIZE;
464 Status = NtProtectVirtualMemory(hProcess,
465 (PVOID*)&Stack,
466 &GuardPageSize,
467 PAGE_GUARD | PAGE_READWRITE,
468 &Dummy);
469 if (!NT_SUCCESS(Status))
470 {
471 DPRINT1("Failure to set guard page\n");
472 return Status;
473 }
474
475 /* Update the Stack Limit keeping in mind the Guard Page */
476 InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit +
477 GuardPageSize);
478 }
479
480 /* We are done! */
481 return STATUS_SUCCESS;
482 }
483
484 VOID
485 WINAPI
486 BaseFreeThreadStack(IN HANDLE hProcess,
487 IN PINITIAL_TEB InitialTeb)
488 {
489 SIZE_T Dummy = 0;
490
491 /* Free the Stack */
492 NtFreeVirtualMemory(hProcess,
493 &InitialTeb->AllocatedStackBase,
494 &Dummy,
495 MEM_RELEASE);
496 }
497
498 /*
499 * Creates the Initial Context for a Thread or Fiber
500 */
501 VOID
502 WINAPI
503 BaseInitializeContext(IN PCONTEXT Context,
504 IN PVOID Parameter,
505 IN PVOID StartAddress,
506 IN PVOID StackAddress,
507 IN ULONG ContextType)
508 {
509 #ifdef _M_IX86
510 ULONG ContextFlags;
511 DPRINT("BaseInitializeContext: %p\n", Context);
512
513 /* Setup the Initial Win32 Thread Context */
514 Context->Eax = (ULONG)StartAddress;
515 Context->Ebx = (ULONG)Parameter;
516 Context->Esp = (ULONG)StackAddress;
517 /* The other registers are undefined */
518
519 /* Setup the Segments */
520 Context->SegFs = KGDT_R3_TEB;
521 Context->SegEs = KGDT_R3_DATA;
522 Context->SegDs = KGDT_R3_DATA;
523 Context->SegCs = KGDT_R3_CODE;
524 Context->SegSs = KGDT_R3_DATA;
525 Context->SegGs = 0;
526
527 /* Set the Context Flags */
528 ContextFlags = Context->ContextFlags;
529 Context->ContextFlags = CONTEXT_FULL;
530
531 /* Give it some room for the Parameter */
532 Context->Esp -= sizeof(PVOID);
533
534 /* Set the EFLAGS */
535 Context->EFlags = 0x3000; /* IOPL 3 */
536
537 /* What kind of context is being created? */
538 if (ContextType == 1)
539 {
540 /* For Threads */
541 Context->Eip = (ULONG)BaseThreadStartupThunk;
542 }
543 else if (ContextType == 2)
544 {
545 /* This is a fiber: make space for the return address */
546 Context->Esp -= sizeof(PVOID);
547 *((PVOID*)Context->Esp) = BaseFiberStartup;
548
549 /* Is FPU state required? */
550 Context->ContextFlags |= ContextFlags;
551 if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
552 {
553 /* Set an initial state */
554 Context->FloatSave.ControlWord = 0x27F;
555 Context->FloatSave.StatusWord = 0;
556 Context->FloatSave.TagWord = 0xFFFF;
557 Context->FloatSave.ErrorOffset = 0;
558 Context->FloatSave.ErrorSelector = 0;
559 Context->FloatSave.DataOffset = 0;
560 Context->FloatSave.DataSelector = 0;
561 if (SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE])
562 Context->Dr6 = 0x1F80;
563 }
564 }
565 else
566 {
567 /* For first thread in a Process */
568 Context->Eip = (ULONG)BaseProcessStartThunk;
569 }
570
571 #elif defined(_M_AMD64)
572 DPRINT("BaseInitializeContext: %p\n", Context);
573
574 /* Setup the Initial Win32 Thread Context */
575 Context->Rax = (ULONG_PTR)StartAddress;
576 Context->Rbx = (ULONG_PTR)Parameter;
577 Context->Rsp = (ULONG_PTR)StackAddress;
578 /* The other registers are undefined */
579
580 /* Setup the Segments */
581 Context->SegGs = KGDT64_R3_DATA | RPL_MASK;
582 Context->SegEs = KGDT64_R3_DATA | RPL_MASK;
583 Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
584 Context->SegCs = KGDT64_R3_CODE | RPL_MASK;
585 Context->SegSs = KGDT64_R3_DATA | RPL_MASK;
586 Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
587
588 /* Set the EFLAGS */
589 Context->EFlags = 0x3000; /* IOPL 3 */
590
591 if (ContextType == 1) /* For Threads */
592 {
593 Context->Rip = (ULONG_PTR)BaseThreadStartupThunk;
594 }
595 else if (ContextType == 2) /* For Fibers */
596 {
597 Context->Rip = (ULONG_PTR)BaseFiberStartup;
598 }
599 else /* For first thread in a Process */
600 {
601 Context->Rip = (ULONG_PTR)BaseProcessStartThunk;
602 }
603
604 /* Set the Context Flags */
605 Context->ContextFlags = CONTEXT_FULL;
606
607 /* Give it some room for the Parameter */
608 Context->Rsp -= sizeof(PVOID);
609 #elif defined(_M_ARM)
610 DPRINT("BaseInitializeContext: %p\n", Context);
611
612 // FIXME: check if this is correct!
613 /* Setup the Initial Win32 Thread Context */
614 Context->R0 = (ULONG_PTR)StartAddress;
615 Context->R1 = (ULONG_PTR)Parameter;
616 Context->Sp = (ULONG_PTR)StackAddress;
617
618 if (ContextType == 1) /* For Threads */
619 {
620 Context->Pc = (ULONG_PTR)BaseThreadStartupThunk;
621 }
622 else if (ContextType == 2) /* For Fibers */
623 {
624 Context->Pc = (ULONG_PTR)BaseFiberStartup;
625 }
626 else /* For first thread in a Process */
627 {
628 Context->Pc = (ULONG_PTR)BaseProcessStartThunk;
629 }
630
631 /* Set the Context Flags */
632 Context->ContextFlags = CONTEXT_FULL;
633
634 /* Give it some room for the Parameter */
635 Context->Sp -= sizeof(PVOID);
636 #else
637 #warning Unknown architecture
638 UNIMPLEMENTED;
639 DbgBreakPoint();
640 #endif
641 }
642
643 /*
644 * Checks if the privilege for Real-Time Priority is there
645 * Beware about this function behavior:
646 * - In case Keep is set to FALSE, then the function will only check
647 * whether real time is allowed and won't grant the privilege. In that case
648 * it will return TRUE if allowed, FALSE otherwise. Not a state!
649 * It means you don't have to release privilege when calling with FALSE.
650 */
651 PVOID
652 WINAPI
653 BasepIsRealtimeAllowed(IN BOOLEAN Keep)
654 {
655 ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
656 PVOID State;
657 NTSTATUS Status;
658
659 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
660 if (!NT_SUCCESS(Status)) return NULL;
661
662 if (!Keep)
663 {
664 RtlReleasePrivilege(State);
665 State = (PVOID)TRUE;
666 }
667
668 return State;
669 }
670
671 /*
672 * Maps an image file into a section
673 */
674 NTSTATUS
675 WINAPI
676 BasepMapFile(IN LPCWSTR lpApplicationName,
677 OUT PHANDLE hSection,
678 IN PUNICODE_STRING ApplicationName)
679 {
680 RTL_RELATIVE_NAME_U RelativeName;
681 OBJECT_ATTRIBUTES ObjectAttributes;
682 NTSTATUS Status;
683 HANDLE hFile = NULL;
684 IO_STATUS_BLOCK IoStatusBlock;
685
686 DPRINT("BasepMapFile\n");
687
688 /* Zero out the Relative Directory */
689 RelativeName.ContainingDirectory = NULL;
690
691 /* Find the application name */
692 if (!RtlDosPathNameToNtPathName_U(lpApplicationName,
693 ApplicationName,
694 NULL,
695 &RelativeName))
696 {
697 return STATUS_OBJECT_PATH_NOT_FOUND;
698 }
699
700 DPRINT("ApplicationName %wZ\n", ApplicationName);
701 DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName);
702
703 /* Did we get a relative name? */
704 if (RelativeName.RelativeName.Length)
705 {
706 ApplicationName = &RelativeName.RelativeName;
707 }
708
709 /* Initialize the Object Attributes */
710 InitializeObjectAttributes(&ObjectAttributes,
711 ApplicationName,
712 OBJ_CASE_INSENSITIVE,
713 RelativeName.ContainingDirectory,
714 NULL);
715
716 /* Try to open the executable */
717 Status = NtOpenFile(&hFile,
718 SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
719 &ObjectAttributes,
720 &IoStatusBlock,
721 FILE_SHARE_DELETE | FILE_SHARE_READ,
722 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
723 if (!NT_SUCCESS(Status))
724 {
725 DPRINT1("Failed to open file\n");
726 BaseSetLastNTError(Status);
727 return Status;
728 }
729
730 /* Create a section for this file */
731 Status = NtCreateSection(hSection,
732 SECTION_ALL_ACCESS,
733 NULL,
734 NULL,
735 PAGE_EXECUTE,
736 SEC_IMAGE,
737 hFile);
738 NtClose(hFile);
739
740 /* Return status */
741 DPRINT("Section: %p for file: %p\n", *hSection, hFile);
742 return Status;
743 }
744
745 /*
746 * @implemented
747 */
748 BOOLEAN
749 WINAPI
750 Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection)
751 {
752 NTSTATUS Status;
753 BOOL Result;
754
755 Status = RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection);
756 if (NT_SUCCESS(Status))
757 {
758 Result = TRUE;
759 }
760 else
761 {
762 BaseSetLastNTError(Status);
763 Result = FALSE;
764 }
765 return Result;
766 }
767
768 /*
769 * @implemented
770 */
771 BOOL
772 WINAPI
773 Wow64DisableWow64FsRedirection(IN PVOID *OldValue)
774 {
775 NTSTATUS Status;
776 BOOL Result;
777
778 Status = RtlWow64EnableFsRedirectionEx((PVOID)TRUE, OldValue);
779 if (NT_SUCCESS(Status))
780 {
781 Result = TRUE;
782 }
783 else
784 {
785 BaseSetLastNTError(Status);
786 Result = FALSE;
787 }
788 return Result;
789 }
790
791 /*
792 * @implemented
793 */
794 BOOL
795 WINAPI
796 Wow64RevertWow64FsRedirection(IN PVOID OldValue)
797 {
798 NTSTATUS Status;
799 BOOL Result;
800
801 Status = RtlWow64EnableFsRedirectionEx(OldValue, &OldValue);
802 if (NT_SUCCESS(Status))
803 {
804 Result = TRUE;
805 }
806 else
807 {
808 BaseSetLastNTError(Status);
809 Result = FALSE;
810 }
811 return Result;
812 }
813
814 /*
815 * @implemented
816 */
817 VOID
818 WINAPI
819 SetFileApisToOEM(VOID)
820 {
821 /* Set the correct Base Api */
822 Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
823 BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
824 BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
825 Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
826
827 /* FIXME: Old, deprecated way */
828 bIsFileApiAnsi = FALSE;
829 }
830
831
832 /*
833 * @implemented
834 */
835 VOID
836 WINAPI
837 SetFileApisToANSI(VOID)
838 {
839 /* Set the correct Base Api */
840 Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
841 BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
842 BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
843 Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
844
845 /* FIXME: Old, deprecated way */
846 bIsFileApiAnsi = TRUE;
847 }
848
849 /*
850 * @implemented
851 */
852 BOOL
853 WINAPI
854 AreFileApisANSI(VOID)
855 {
856 return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
857 }
858
859 /*
860 * @implemented
861 */
862 VOID
863 WINAPI
864 BaseMarkFileForDelete(IN HANDLE FileHandle,
865 IN ULONG FileAttributes)
866 {
867 IO_STATUS_BLOCK IoStatusBlock;
868 FILE_BASIC_INFORMATION FileBasicInfo;
869 FILE_DISPOSITION_INFORMATION FileDispositionInfo;
870
871 /* If no attributes were given, get them */
872 if (!FileAttributes)
873 {
874 FileBasicInfo.FileAttributes = 0;
875 NtQueryInformationFile(FileHandle,
876 &IoStatusBlock,
877 &FileBasicInfo,
878 sizeof(FileBasicInfo),
879 FileBasicInformation);
880 FileAttributes = FileBasicInfo.FileAttributes;
881 }
882
883 /* If file is marked as RO, reset its attributes */
884 if (FileAttributes & FILE_ATTRIBUTE_READONLY)
885 {
886 RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
887 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
888 NtSetInformationFile(FileHandle,
889 &IoStatusBlock,
890 &FileBasicInfo,
891 sizeof(FileBasicInfo),
892 FileBasicInformation);
893 }
894
895 /* Finally, mark the file for deletion */
896 FileDispositionInfo.DeleteFile = TRUE;
897 NtSetInformationFile(FileHandle,
898 &IoStatusBlock,
899 &FileDispositionInfo,
900 sizeof(FileDispositionInfo),
901 FileDispositionInformation);
902 }
903
904 /*
905 * @unimplemented
906 */
907 NTSTATUS
908 WINAPI
909 BasepCheckWinSaferRestrictions(IN HANDLE UserToken,
910 IN LPWSTR ApplicationName,
911 IN HANDLE FileHandle,
912 OUT PBOOLEAN InJob,
913 OUT PHANDLE NewToken,
914 OUT PHANDLE JobHandle)
915 {
916 NTSTATUS Status;
917
918 /* Validate that there's a name */
919 if ((ApplicationName) && *(ApplicationName))
920 {
921 /* Validate that the required output parameters are there */
922 if ((InJob) && (NewToken) && (JobHandle))
923 {
924 /* Do the work (one day...) */
925 DPRINT("BasepCheckWinSaferRestrictions is UNIMPLEMENTED\n");
926 Status = STATUS_SUCCESS;
927 }
928 else
929 {
930 /* Act as if SEH hit this */
931 Status = STATUS_ACCESS_VIOLATION;
932 }
933 }
934 else
935 {
936 /* Input is invalid */
937 Status = STATUS_INVALID_PARAMETER;
938 }
939
940 /* Return the status */
941 return Status;
942 }