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