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