[KERNEL32] Improve the FILE header section. Brought to you by Adam Stachowicz. CORE...
[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 BOOL
908 WINAPI
909 BaseCheckRunApp(IN DWORD Unknown1,
910 IN DWORD Unknown2,
911 IN DWORD Unknown3,
912 IN DWORD Unknown4,
913 IN DWORD Unknown5,
914 IN DWORD Unknown6,
915 IN DWORD Unknown7,
916 IN DWORD Unknown8,
917 IN DWORD Unknown9,
918 IN DWORD Unknown10)
919 {
920 STUB;
921 return FALSE;
922 }
923
924 /*
925 * @unimplemented
926 */
927 NTSTATUS
928 WINAPI
929 BasepCheckWinSaferRestrictions(IN HANDLE UserToken,
930 IN LPWSTR ApplicationName,
931 IN HANDLE FileHandle,
932 OUT PBOOLEAN InJob,
933 OUT PHANDLE NewToken,
934 OUT PHANDLE JobHandle)
935 {
936 NTSTATUS Status;
937
938 /* Validate that there's a name */
939 if ((ApplicationName) && *(ApplicationName))
940 {
941 /* Validate that the required output parameters are there */
942 if ((InJob) && (NewToken) && (JobHandle))
943 {
944 /* Do the work (one day...) */
945 UNIMPLEMENTED;
946 Status = STATUS_SUCCESS;
947 }
948 else
949 {
950 /* Act as if SEH hit this */
951 Status = STATUS_ACCESS_VIOLATION;
952 }
953 }
954 else
955 {
956 /* Input is invalid */
957 Status = STATUS_INVALID_PARAMETER;
958 }
959
960 /* Return the status */
961 return Status;
962 }