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 * NOTE: Adapted from sdk/lib/rtl/thread.c:RtlpCreateUserStack(). 351 */ 352 NTSTATUS 353 WINAPI 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 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 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 584 /* Setup the Initial Win32 Thread Context */ 585 Context->Rax = (ULONG_PTR)StartAddress; 586 Context->Rbx = (ULONG_PTR)Parameter; 587 Context->Rsp = (ULONG_PTR)StackAddress; 588 /* The other registers are undefined */ 589 590 /* Setup the Segments */ 591 Context->SegGs = KGDT64_R3_DATA | RPL_MASK; 592 Context->SegEs = KGDT64_R3_DATA | RPL_MASK; 593 Context->SegDs = KGDT64_R3_DATA | RPL_MASK; 594 Context->SegCs = KGDT64_R3_CODE | RPL_MASK; 595 Context->SegSs = KGDT64_R3_DATA | RPL_MASK; 596 Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK; 597 598 /* Set the EFLAGS */ 599 Context->EFlags = 0x3000; /* IOPL 3 */ 600 601 if (ContextType == 1) /* For Threads */ 602 { 603 Context->Rip = (ULONG_PTR)BaseThreadStartupThunk; 604 } 605 else if (ContextType == 2) /* For Fibers */ 606 { 607 Context->Rip = (ULONG_PTR)BaseFiberStartup; 608 } 609 else /* For first thread in a Process */ 610 { 611 Context->Rip = (ULONG_PTR)BaseProcessStartThunk; 612 } 613 614 /* Set the Context Flags */ 615 Context->ContextFlags = CONTEXT_FULL; 616 617 /* Give it some room for the Parameter */ 618 Context->Rsp -= sizeof(PVOID); 619 #elif defined(_M_ARM) 620 DPRINT("BaseInitializeContext: %p\n", Context); 621 622 // FIXME: check if this is correct! 623 /* Setup the Initial Win32 Thread Context */ 624 Context->R0 = (ULONG_PTR)StartAddress; 625 Context->R1 = (ULONG_PTR)Parameter; 626 Context->Sp = (ULONG_PTR)StackAddress; 627 628 if (ContextType == 1) /* For Threads */ 629 { 630 Context->Pc = (ULONG_PTR)BaseThreadStartupThunk; 631 } 632 else if (ContextType == 2) /* For Fibers */ 633 { 634 Context->Pc = (ULONG_PTR)BaseFiberStartup; 635 } 636 else /* For first thread in a Process */ 637 { 638 Context->Pc = (ULONG_PTR)BaseProcessStartThunk; 639 } 640 641 /* Set the Context Flags */ 642 Context->ContextFlags = CONTEXT_FULL; 643 644 /* Give it some room for the Parameter */ 645 Context->Sp -= sizeof(PVOID); 646 #else 647 #warning Unknown architecture 648 UNIMPLEMENTED; 649 DbgBreakPoint(); 650 #endif 651 } 652 653 /* 654 * Checks if the privilege for Real-Time Priority is there 655 * Beware about this function behavior: 656 * - In case Keep is set to FALSE, then the function will only check 657 * whether real time is allowed and won't grant the privilege. In that case 658 * it will return TRUE if allowed, FALSE otherwise. Not a state! 659 * It means you don't have to release privilege when calling with FALSE. 660 */ 661 PVOID 662 WINAPI 663 BasepIsRealtimeAllowed(IN BOOLEAN Keep) 664 { 665 ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE; 666 PVOID State; 667 NTSTATUS Status; 668 669 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State); 670 if (!NT_SUCCESS(Status)) return NULL; 671 672 if (!Keep) 673 { 674 RtlReleasePrivilege(State); 675 State = (PVOID)TRUE; 676 } 677 678 return State; 679 } 680 681 /* 682 * Maps an image file into a section 683 */ 684 NTSTATUS 685 WINAPI 686 BasepMapFile(IN LPCWSTR lpApplicationName, 687 OUT PHANDLE hSection, 688 IN PUNICODE_STRING ApplicationName) 689 { 690 RTL_RELATIVE_NAME_U RelativeName; 691 OBJECT_ATTRIBUTES ObjectAttributes; 692 NTSTATUS Status; 693 HANDLE hFile = NULL; 694 IO_STATUS_BLOCK IoStatusBlock; 695 696 DPRINT("BasepMapFile\n"); 697 698 /* Zero out the Relative Directory */ 699 RelativeName.ContainingDirectory = NULL; 700 701 /* Find the application name */ 702 if (!RtlDosPathNameToNtPathName_U(lpApplicationName, 703 ApplicationName, 704 NULL, 705 &RelativeName)) 706 { 707 return STATUS_OBJECT_PATH_NOT_FOUND; 708 } 709 710 DPRINT("ApplicationName %wZ\n", ApplicationName); 711 DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName); 712 713 /* Did we get a relative name? */ 714 if (RelativeName.RelativeName.Length) 715 { 716 ApplicationName = &RelativeName.RelativeName; 717 } 718 719 /* Initialize the Object Attributes */ 720 InitializeObjectAttributes(&ObjectAttributes, 721 ApplicationName, 722 OBJ_CASE_INSENSITIVE, 723 RelativeName.ContainingDirectory, 724 NULL); 725 726 /* Try to open the executable */ 727 Status = NtOpenFile(&hFile, 728 SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, 729 &ObjectAttributes, 730 &IoStatusBlock, 731 FILE_SHARE_DELETE | FILE_SHARE_READ, 732 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); 733 if (!NT_SUCCESS(Status)) 734 { 735 DPRINT1("Failed to open file\n"); 736 BaseSetLastNTError(Status); 737 return Status; 738 } 739 740 /* Create a section for this file */ 741 Status = NtCreateSection(hSection, 742 SECTION_ALL_ACCESS, 743 NULL, 744 NULL, 745 PAGE_EXECUTE, 746 SEC_IMAGE, 747 hFile); 748 NtClose(hFile); 749 750 /* Return status */ 751 DPRINT("Section: %p for file: %p\n", *hSection, hFile); 752 return Status; 753 } 754 755 /* 756 * @implemented 757 */ 758 BOOLEAN 759 WINAPI 760 Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection) 761 { 762 NTSTATUS Status; 763 BOOL Result; 764 765 Status = RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection); 766 if (NT_SUCCESS(Status)) 767 { 768 Result = TRUE; 769 } 770 else 771 { 772 BaseSetLastNTError(Status); 773 Result = FALSE; 774 } 775 return Result; 776 } 777 778 /* 779 * @implemented 780 */ 781 BOOL 782 WINAPI 783 Wow64DisableWow64FsRedirection(IN PVOID *OldValue) 784 { 785 NTSTATUS Status; 786 BOOL Result; 787 788 Status = RtlWow64EnableFsRedirectionEx((PVOID)TRUE, OldValue); 789 if (NT_SUCCESS(Status)) 790 { 791 Result = TRUE; 792 } 793 else 794 { 795 BaseSetLastNTError(Status); 796 Result = FALSE; 797 } 798 return Result; 799 } 800 801 /* 802 * @implemented 803 */ 804 BOOL 805 WINAPI 806 Wow64RevertWow64FsRedirection(IN PVOID OldValue) 807 { 808 NTSTATUS Status; 809 BOOL Result; 810 811 Status = RtlWow64EnableFsRedirectionEx(OldValue, &OldValue); 812 if (NT_SUCCESS(Status)) 813 { 814 Result = TRUE; 815 } 816 else 817 { 818 BaseSetLastNTError(Status); 819 Result = FALSE; 820 } 821 return Result; 822 } 823 824 /* 825 * @implemented 826 */ 827 VOID 828 WINAPI 829 SetFileApisToOEM(VOID) 830 { 831 /* Set the correct Base Api */ 832 Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString; 833 BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString; 834 BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize; 835 Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize; 836 837 /* FIXME: Old, deprecated way */ 838 bIsFileApiAnsi = FALSE; 839 } 840 841 842 /* 843 * @implemented 844 */ 845 VOID 846 WINAPI 847 SetFileApisToANSI(VOID) 848 { 849 /* Set the correct Base Api */ 850 Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; 851 BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString; 852 BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize; 853 Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize; 854 855 /* FIXME: Old, deprecated way */ 856 bIsFileApiAnsi = TRUE; 857 } 858 859 /* 860 * @implemented 861 */ 862 BOOL 863 WINAPI 864 AreFileApisANSI(VOID) 865 { 866 return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString; 867 } 868 869 /* 870 * @implemented 871 */ 872 VOID 873 WINAPI 874 BaseMarkFileForDelete(IN HANDLE FileHandle, 875 IN ULONG FileAttributes) 876 { 877 IO_STATUS_BLOCK IoStatusBlock; 878 FILE_BASIC_INFORMATION FileBasicInfo; 879 FILE_DISPOSITION_INFORMATION FileDispositionInfo; 880 881 /* If no attributes were given, get them */ 882 if (!FileAttributes) 883 { 884 FileBasicInfo.FileAttributes = 0; 885 NtQueryInformationFile(FileHandle, 886 &IoStatusBlock, 887 &FileBasicInfo, 888 sizeof(FileBasicInfo), 889 FileBasicInformation); 890 FileAttributes = FileBasicInfo.FileAttributes; 891 } 892 893 /* If file is marked as RO, reset its attributes */ 894 if (FileAttributes & FILE_ATTRIBUTE_READONLY) 895 { 896 RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo)); 897 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; 898 NtSetInformationFile(FileHandle, 899 &IoStatusBlock, 900 &FileBasicInfo, 901 sizeof(FileBasicInfo), 902 FileBasicInformation); 903 } 904 905 /* Finally, mark the file for deletion */ 906 FileDispositionInfo.DeleteFile = TRUE; 907 NtSetInformationFile(FileHandle, 908 &IoStatusBlock, 909 &FileDispositionInfo, 910 sizeof(FileDispositionInfo), 911 FileDispositionInformation); 912 } 913 914 /* 915 * @unimplemented 916 */ 917 NTSTATUS 918 WINAPI 919 BasepCheckWinSaferRestrictions(IN HANDLE UserToken, 920 IN LPWSTR ApplicationName, 921 IN HANDLE FileHandle, 922 OUT PBOOLEAN InJob, 923 OUT PHANDLE NewToken, 924 OUT PHANDLE JobHandle) 925 { 926 NTSTATUS Status; 927 928 /* Validate that there's a name */ 929 if ((ApplicationName) && *(ApplicationName)) 930 { 931 /* Validate that the required output parameters are there */ 932 if ((InJob) && (NewToken) && (JobHandle)) 933 { 934 /* Do the work (one day...) */ 935 DPRINT("BasepCheckWinSaferRestrictions is UNIMPLEMENTED\n"); 936 Status = STATUS_SUCCESS; 937 } 938 else 939 { 940 /* Act as if SEH hit this */ 941 Status = STATUS_ACCESS_VIOLATION; 942 } 943 } 944 else 945 { 946 /* Input is invalid */ 947 Status = STATUS_INVALID_PARAMETER; 948 } 949 950 /* Return the status */ 951 return Status; 952 } 953