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