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 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 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 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 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 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 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 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 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 866 AreFileApisANSI(VOID) 867 { 868 return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString; 869 } 870 871 /* 872 * @implemented 873 */ 874 VOID 875 WINAPI 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 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