1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS NT User-Mode DLL 4 * FILE: lib/ntdll/rtl/libsup.c 5 * PURPOSE: RTL Support Routines 6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7 * Gunnar Dalsnes 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntdll.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 SIZE_T RtlpAllocDeallocQueryBufferSize = PAGE_SIZE; 18 PTEB LdrpTopLevelDllBeingLoadedTeb = NULL; 19 PVOID MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS; 20 21 /* FUNCTIONS ***************************************************************/ 22 23 BOOLEAN 24 NTAPI 25 RtlpCheckForActiveDebugger(VOID) 26 { 27 /* Return the flag in the PEB */ 28 return NtCurrentPeb()->BeingDebugged; 29 } 30 31 BOOLEAN 32 NTAPI 33 RtlpSetInDbgPrint(VOID) 34 { 35 /* Check if it's already set and return TRUE if so */ 36 if (NtCurrentTeb()->InDbgPrint) return TRUE; 37 38 /* Set it and return */ 39 NtCurrentTeb()->InDbgPrint = TRUE; 40 return FALSE; 41 } 42 43 VOID 44 NTAPI 45 RtlpClearInDbgPrint(VOID) 46 { 47 /* Clear the flag */ 48 NtCurrentTeb()->InDbgPrint = FALSE; 49 } 50 51 KPROCESSOR_MODE 52 NTAPI 53 RtlpGetMode(VOID) 54 { 55 return UserMode; 56 } 57 58 /* 59 * @implemented 60 */ 61 PPEB 62 NTAPI 63 RtlGetCurrentPeb(VOID) 64 { 65 return NtCurrentPeb(); 66 } 67 68 /* 69 * @implemented 70 */ 71 VOID NTAPI 72 RtlAcquirePebLock(VOID) 73 { 74 PPEB Peb = NtCurrentPeb (); 75 RtlEnterCriticalSection(Peb->FastPebLock); 76 } 77 78 /* 79 * @implemented 80 */ 81 VOID NTAPI 82 RtlReleasePebLock(VOID) 83 { 84 PPEB Peb = NtCurrentPeb (); 85 RtlLeaveCriticalSection(Peb->FastPebLock); 86 } 87 88 /* 89 * @implemented 90 */ 91 ULONG 92 NTAPI 93 RtlGetNtGlobalFlags(VOID) 94 { 95 PPEB pPeb = NtCurrentPeb(); 96 return pPeb->NtGlobalFlag; 97 } 98 99 NTSTATUS 100 NTAPI 101 RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock) 102 { 103 return RtlDeleteCriticalSection(&Lock->CriticalSection); 104 } 105 106 NTSTATUS 107 NTAPI 108 RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive) 109 { 110 UNREFERENCED_PARAMETER(Exclusive); 111 112 return RtlEnterCriticalSection(&Lock->CriticalSection); 113 } 114 115 BOOLEAN 116 NTAPI 117 RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive) 118 { 119 UNREFERENCED_PARAMETER(Exclusive); 120 121 return RtlTryEnterCriticalSection(&Lock->CriticalSection); 122 } 123 124 NTSTATUS 125 NTAPI 126 RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock) 127 { 128 return RtlInitializeCriticalSection(&(*Lock)->CriticalSection); 129 } 130 131 NTSTATUS 132 NTAPI 133 RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock) 134 { 135 return RtlLeaveCriticalSection(&Lock->CriticalSection); 136 } 137 138 PVOID 139 NTAPI 140 RtlpAllocateMemory(UINT Bytes, 141 ULONG Tag) 142 { 143 UNREFERENCED_PARAMETER(Tag); 144 145 return RtlAllocateHeap(RtlGetProcessHeap(), 146 0, 147 Bytes); 148 } 149 150 151 VOID 152 NTAPI 153 RtlpFreeMemory(PVOID Mem, 154 ULONG Tag) 155 { 156 UNREFERENCED_PARAMETER(Tag); 157 158 RtlFreeHeap(RtlGetProcessHeap(), 159 0, 160 Mem); 161 } 162 163 164 #if DBG 165 VOID FASTCALL 166 CHECK_PAGED_CODE_RTL(char *file, int line) 167 { 168 /* meaningless in user mode */ 169 } 170 #endif 171 172 VOID 173 NTAPI 174 RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters) 175 { 176 PPEB Peb; 177 178 /* Get PEB */ 179 Peb = RtlGetCurrentPeb(); 180 181 /* Apply defaults for non-set parameters */ 182 if (!Parameters->SegmentCommit) Parameters->SegmentCommit = Peb->HeapSegmentCommit; 183 if (!Parameters->SegmentReserve) Parameters->SegmentReserve = Peb->HeapSegmentReserve; 184 if (!Parameters->DeCommitFreeBlockThreshold) Parameters->DeCommitFreeBlockThreshold = Peb->HeapDeCommitFreeBlockThreshold; 185 if (!Parameters->DeCommitTotalFreeThreshold) Parameters->DeCommitTotalFreeThreshold = Peb->HeapDeCommitTotalFreeThreshold; 186 } 187 188 BOOLEAN 189 NTAPI 190 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, 191 IN ULONG_PTR RegistrationFrameEnd, 192 IN OUT PULONG_PTR StackLow, 193 IN OUT PULONG_PTR StackHigh) 194 { 195 /* There's no such thing as a DPC stack in user-mode */ 196 return FALSE; 197 } 198 199 VOID 200 NTAPI 201 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord, 202 IN PCONTEXT ContextRecord, 203 IN PVOID ContextData, 204 IN ULONG Size) 205 { 206 /* Exception logging is not done in user-mode */ 207 } 208 209 BOOLEAN 210 NTAPI 211 RtlpCaptureStackLimits(IN ULONG_PTR Ebp, 212 IN ULONG_PTR *StackBegin, 213 IN ULONG_PTR *StackEnd) 214 { 215 /* FIXME: Verify */ 216 *StackBegin = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit; 217 *StackEnd = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase; 218 return TRUE; 219 } 220 221 #ifndef _M_AMD64 222 /* 223 * @implemented 224 */ 225 ULONG 226 NTAPI 227 RtlWalkFrameChain(OUT PVOID *Callers, 228 IN ULONG Count, 229 IN ULONG Flags) 230 { 231 ULONG_PTR Stack, NewStack, StackBegin, StackEnd = 0; 232 ULONG Eip; 233 BOOLEAN Result, StopSearch = FALSE; 234 ULONG i = 0; 235 236 /* Get current EBP */ 237 #if defined(_M_IX86) 238 #if defined __GNUC__ 239 __asm__("mov %%ebp, %0" : "=r" (Stack) : ); 240 #elif defined(_MSC_VER) 241 __asm mov Stack, ebp 242 #endif 243 #elif defined(_M_MIPS) 244 __asm__("move $sp, %0" : "=r" (Stack) : ); 245 #elif defined(_M_PPC) 246 __asm__("mr %0,1" : "=r" (Stack) : ); 247 #elif defined(_M_ARM) 248 #if defined __GNUC__ 249 __asm__("mov sp, %0" : "=r"(Stack) : ); 250 #elif defined(_MSC_VER) 251 // FIXME: Hack. Probably won't work if this ever actually manages to run someday. 252 Stack = (ULONG_PTR)&Stack; 253 #endif 254 #else 255 #error Unknown architecture 256 #endif 257 258 /* Set it as the stack begin limit as well */ 259 StackBegin = (ULONG_PTR)Stack; 260 261 /* Check if we're called for non-logging mode */ 262 if (!Flags) 263 { 264 /* Get the actual safe limits */ 265 Result = RtlpCaptureStackLimits((ULONG_PTR)Stack, 266 &StackBegin, 267 &StackEnd); 268 if (!Result) return 0; 269 } 270 271 /* Use a SEH block for maximum protection */ 272 _SEH2_TRY 273 { 274 /* Loop the frames */ 275 for (i = 0; i < Count; i++) 276 { 277 /* 278 * Leave if we're past the stack, 279 * if we're before the stack, 280 * or if we've reached ourselves. 281 */ 282 if ((Stack >= StackEnd) || 283 (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) || 284 ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR)))) 285 { 286 /* We're done or hit a bad address */ 287 break; 288 } 289 290 /* Get new stack and EIP */ 291 NewStack = *(PULONG_PTR)Stack; 292 Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR)); 293 294 /* Check if the new pointer is above the oldone and past the end */ 295 if (!((Stack < NewStack) && (NewStack < StackEnd))) 296 { 297 /* Stop searching after this entry */ 298 StopSearch = TRUE; 299 } 300 301 /* Also make sure that the EIP isn't a stack address */ 302 if ((StackBegin < Eip) && (Eip < StackEnd)) break; 303 304 /* FIXME: Check that EIP is inside a loaded module */ 305 306 /* Save this frame */ 307 Callers[i] = (PVOID)Eip; 308 309 /* Check if we should continue */ 310 if (StopSearch) 311 { 312 /* Return the next index */ 313 i++; 314 break; 315 } 316 317 /* Move to the next stack */ 318 Stack = NewStack; 319 } 320 } 321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 322 { 323 /* No index */ 324 i = 0; 325 } 326 _SEH2_END; 327 328 /* Return frames parsed */ 329 return i; 330 } 331 #endif 332 333 #ifdef _AMD64_ 334 VOID 335 NTAPI 336 RtlpGetStackLimits( 337 OUT PULONG_PTR LowLimit, 338 OUT PULONG_PTR HighLimit) 339 { 340 *LowLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit; 341 *HighLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase; 342 return; 343 } 344 #endif 345 346 BOOLEAN 347 NTAPI 348 RtlIsThreadWithinLoaderCallout(VOID) 349 { 350 return LdrpTopLevelDllBeingLoadedTeb == NtCurrentTeb(); 351 } 352 353 /* RTL Atom Tables ************************************************************/ 354 355 typedef struct _RTL_ATOM_HANDLE 356 { 357 RTL_HANDLE_TABLE_ENTRY Handle; 358 PRTL_ATOM_TABLE_ENTRY AtomEntry; 359 } RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE; 360 361 NTSTATUS 362 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable) 363 { 364 RtlInitializeCriticalSection(&AtomTable->CriticalSection); 365 return STATUS_SUCCESS; 366 } 367 368 369 VOID 370 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable) 371 { 372 RtlDeleteCriticalSection(&AtomTable->CriticalSection); 373 } 374 375 376 BOOLEAN 377 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable) 378 { 379 RtlEnterCriticalSection(&AtomTable->CriticalSection); 380 return TRUE; 381 } 382 383 384 VOID 385 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable) 386 { 387 RtlLeaveCriticalSection(&AtomTable->CriticalSection); 388 } 389 390 391 /* handle functions */ 392 393 BOOLEAN 394 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable) 395 { 396 RtlInitializeHandleTable(0xCFFF, 397 sizeof(RTL_ATOM_HANDLE), 398 &AtomTable->RtlHandleTable); 399 400 return TRUE; 401 } 402 403 VOID 404 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable) 405 { 406 RtlDestroyHandleTable(&AtomTable->RtlHandleTable); 407 } 408 409 PRTL_ATOM_TABLE 410 RtlpAllocAtomTable(ULONG Size) 411 { 412 return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(), 413 HEAP_ZERO_MEMORY, 414 Size); 415 } 416 417 VOID 418 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable) 419 { 420 RtlFreeHeap(RtlGetProcessHeap(), 421 0, 422 AtomTable); 423 } 424 425 PRTL_ATOM_TABLE_ENTRY 426 RtlpAllocAtomTableEntry(ULONG Size) 427 { 428 return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(), 429 HEAP_ZERO_MEMORY, 430 Size); 431 } 432 433 VOID 434 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry) 435 { 436 RtlFreeHeap(RtlGetProcessHeap(), 437 0, 438 Entry); 439 } 440 441 VOID 442 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry) 443 { 444 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry; 445 446 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable, 447 (ULONG)Entry->HandleIndex, 448 &RtlHandleEntry)) 449 { 450 RtlFreeHandle(&AtomTable->RtlHandleTable, 451 RtlHandleEntry); 452 } 453 } 454 455 BOOLEAN 456 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry) 457 { 458 ULONG HandleIndex; 459 PRTL_HANDLE_TABLE_ENTRY RtlHandle; 460 461 RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable, 462 &HandleIndex); 463 if (RtlHandle != NULL) 464 { 465 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle; 466 467 /* FIXME - Handle Indexes >= 0xC000 ?! */ 468 if (HandleIndex < 0xC000) 469 { 470 Entry->HandleIndex = (USHORT)HandleIndex; 471 Entry->Atom = 0xC000 + (USHORT)HandleIndex; 472 473 AtomHandle->AtomEntry = Entry; 474 AtomHandle->Handle.Flags = RTL_HANDLE_VALID; 475 476 return TRUE; 477 } 478 else 479 { 480 /* set the valid flag, otherwise RtlFreeHandle will fail! */ 481 AtomHandle->Handle.Flags = RTL_HANDLE_VALID; 482 483 RtlFreeHandle(&AtomTable->RtlHandleTable, 484 RtlHandle); 485 } 486 } 487 488 return FALSE; 489 } 490 491 PRTL_ATOM_TABLE_ENTRY 492 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index) 493 { 494 PRTL_HANDLE_TABLE_ENTRY RtlHandle; 495 496 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable, 497 Index, 498 &RtlHandle)) 499 { 500 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle; 501 502 return AtomHandle->AtomEntry; 503 } 504 505 return NULL; 506 } 507 508 509 /* 510 * Ldr Resource support code 511 */ 512 513 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir, 514 LPCWSTR name, void *root, 515 int want_dir ); 516 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir, 517 WORD id, void *root, int want_dir ); 518 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir, 519 void *root, int want_dir ); 520 int push_language( USHORT *list, ULONG pos, WORD lang ); 521 522 /********************************************************************** 523 * find_entry 524 * 525 * Find a resource entry 526 */ 527 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info, 528 ULONG level, void **ret, int want_dir ) 529 { 530 ULONG size; 531 void *root; 532 IMAGE_RESOURCE_DIRECTORY *resdirptr; 533 USHORT list[9]; /* list of languages to try */ 534 int i, pos = 0; 535 LCID user_lcid, system_lcid; 536 537 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size ); 538 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; 539 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; 540 resdirptr = root; 541 542 if (!level--) goto done; 543 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level ))) 544 return STATUS_RESOURCE_TYPE_NOT_FOUND; 545 if (!level--) return STATUS_SUCCESS; 546 547 resdirptr = *ret; 548 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level ))) 549 return STATUS_RESOURCE_NAME_NOT_FOUND; 550 if (!level--) return STATUS_SUCCESS; 551 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */ 552 553 /* 1. specified language */ 554 pos = push_language( list, pos, info->Language ); 555 556 /* 2. specified language with neutral sublanguage */ 557 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) ); 558 559 /* 3. neutral language with neutral sublanguage */ 560 pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); 561 562 /* if no explicitly specified language, try some defaults */ 563 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) 564 { 565 /* user defaults, unless SYS_DEFAULT sublanguage specified */ 566 if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT) 567 { 568 /* 4. current thread locale language */ 569 pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) ); 570 571 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid))) 572 { 573 /* 5. user locale language */ 574 pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) ); 575 576 /* 6. user locale language with neutral sublanguage */ 577 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) ); 578 } 579 } 580 581 /* now system defaults */ 582 583 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid))) 584 { 585 /* 7. system locale language */ 586 pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) ); 587 588 /* 8. system locale language with neutral sublanguage */ 589 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) ); 590 } 591 592 /* 9. English */ 593 pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) ); 594 } 595 596 resdirptr = *ret; 597 for (i = 0; i < pos; i++) 598 if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS; 599 600 /* if no explicitly specified language, return the first entry */ 601 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) 602 { 603 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS; 604 } 605 return STATUS_RESOURCE_LANG_NOT_FOUND; 606 607 done: 608 *ret = resdirptr; 609 return STATUS_SUCCESS; 610 } 611 612 /* 613 * @implemented 614 */ 615 PVOID NTAPI 616 RtlPcToFileHeader(IN PVOID PcValue, 617 PVOID* BaseOfImage) 618 { 619 PLIST_ENTRY ModuleListHead; 620 PLIST_ENTRY Entry; 621 PLDR_DATA_TABLE_ENTRY Module; 622 PVOID ImageBase = NULL; 623 624 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); 625 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 626 Entry = ModuleListHead->Flink; 627 while (Entry != ModuleListHead) 628 { 629 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 630 631 if ((ULONG_PTR)PcValue >= (ULONG_PTR)Module->DllBase && 632 (ULONG_PTR)PcValue < (ULONG_PTR)Module->DllBase + Module->SizeOfImage) 633 { 634 ImageBase = Module->DllBase; 635 break; 636 } 637 Entry = Entry->Flink; 638 } 639 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); 640 641 *BaseOfImage = ImageBase; 642 return ImageBase; 643 } 644 645 NTSTATUS get_buffer(LPWSTR *buffer, SIZE_T needed, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer) 646 { 647 WCHAR *p; 648 649 if (CallerBuffer && CallerBuffer->MaximumLength > needed) 650 { 651 p = CallerBuffer->Buffer; 652 CallerBuffer->Length = needed - sizeof(WCHAR); 653 } 654 else 655 { 656 if (!bAllocateBuffer) 657 return STATUS_BUFFER_TOO_SMALL; 658 659 if (CallerBuffer) 660 CallerBuffer->Buffer[0] = 0; 661 662 p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed ); 663 if (!p) 664 return STATUS_NO_MEMORY; 665 } 666 *buffer = p; 667 668 return STATUS_SUCCESS; 669 } 670 671 /* NOTE: Remove this one once our actctx support becomes better */ 672 NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer) 673 { 674 static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'}; 675 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; 676 677 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; 678 ACTCTX_SECTION_KEYED_DATA data; 679 NTSTATUS status; 680 SIZE_T needed, size = 1024; 681 WCHAR *p; 682 683 data.cbSize = sizeof(data); 684 status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, 685 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, 686 pnameW, &data ); 687 if (status != STATUS_SUCCESS) 688 { 689 //DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW); 690 return status; 691 } 692 693 for (;;) 694 { 695 if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) 696 { 697 status = STATUS_NO_MEMORY; 698 goto done; 699 } 700 status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, 701 AssemblyDetailedInformationInActivationContext, 702 info, size, &needed ); 703 if (status == STATUS_SUCCESS) break; 704 if (status != STATUS_BUFFER_TOO_SMALL) goto done; 705 RtlFreeHeap( RtlGetProcessHeap(), 0, info ); 706 size = needed; 707 } 708 709 DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath); 710 DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); 711 if (!info->lpAssemblyManifestPath /*|| !info->lpAssemblyDirectoryName*/) 712 { 713 status = STATUS_SXS_KEY_NOT_FOUND; 714 goto done; 715 } 716 717 if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' ))) 718 { 719 DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); 720 721 p++; 722 if (!info->lpAssemblyDirectoryName || _wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW )) 723 { 724 /* manifest name does not match directory name, so it's not a global 725 * windows/winsxs manifest; use the manifest directory name instead */ 726 dirlen = p - info->lpAssemblyManifestPath; 727 needed = (dirlen + 1) * sizeof(WCHAR) + pnameW->Length; 728 729 status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer); 730 if (!NT_SUCCESS(status)) 731 goto done; 732 733 p = *fullname; 734 735 memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) ); 736 p += dirlen; 737 memcpy( p, pnameW->Buffer, pnameW->Length); 738 p += (pnameW->Length / sizeof(WCHAR)); 739 *p = L'\0'; 740 741 goto done; 742 } 743 } 744 745 needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) + 746 sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + pnameW->Length + 2*sizeof(WCHAR)); 747 748 status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer); 749 if (!NT_SUCCESS(status)) 750 goto done; 751 752 p = *fullname; 753 754 wcscpy( p, SharedUserData->NtSystemRoot ); 755 p += wcslen(p); 756 memcpy( p, winsxsW, sizeof(winsxsW) ); 757 p += sizeof(winsxsW) / sizeof(WCHAR); 758 memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength ); 759 p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); 760 *p++ = L'\\'; 761 memcpy( p, pnameW->Buffer, pnameW->Length); 762 p += (pnameW->Length / sizeof(WCHAR)); 763 *p = L'\0'; 764 765 done: 766 RtlFreeHeap( RtlGetProcessHeap(), 0, info ); 767 RtlReleaseActivationContext( data.hActCtx ); 768 DPRINT("%S\n", fullname); 769 return status; 770 } 771 772 /* 773 * @unimplemented 774 */ 775 NTSYSAPI 776 NTSTATUS 777 NTAPI 778 RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags, 779 IN PUNICODE_STRING OriginalName, 780 IN PUNICODE_STRING Extension, 781 IN OUT PUNICODE_STRING StaticString, 782 IN OUT PUNICODE_STRING DynamicString, 783 IN OUT PUNICODE_STRING *NewName, 784 IN PULONG NewFlags, 785 IN PSIZE_T FileNameSize, 786 IN PSIZE_T RequiredLength) 787 { 788 NTSTATUS Status; 789 LPWSTR fullname; 790 WCHAR buffer [MAX_PATH]; 791 UNICODE_STRING localStr, localStr2, *pstrParam; 792 WCHAR *p; 793 BOOLEAN GotExtension; 794 WCHAR c; 795 C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR)); 796 797 798 /* Check for invalid parameters */ 799 if (!OriginalName) 800 { 801 return STATUS_INVALID_PARAMETER; 802 } 803 804 if (!DynamicString && !StaticString) 805 { 806 return STATUS_INVALID_PARAMETER; 807 } 808 809 if ((DynamicString) && (StaticString) && !(NewName)) 810 { 811 return STATUS_INVALID_PARAMETER; 812 } 813 814 if (!OriginalName->Buffer || OriginalName->Length == 0) 815 { 816 return STATUS_SXS_KEY_NOT_FOUND; 817 } 818 819 if (StaticString && (OriginalName == StaticString || OriginalName->Buffer == StaticString->Buffer)) 820 { 821 return STATUS_SXS_KEY_NOT_FOUND; 822 } 823 824 if (NtCurrentPeb()->ProcessParameters && 825 (NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH)) 826 { 827 UNICODE_STRING RealName, LocalName; 828 WCHAR RealNameBuf[MAX_PATH], LocalNameBuf[MAX_PATH]; 829 830 RtlInitEmptyUnicodeString(&RealName, RealNameBuf, sizeof(RealNameBuf)); 831 RtlInitEmptyUnicodeString(&LocalName, LocalNameBuf, sizeof(LocalNameBuf)); 832 833 Status = RtlComputePrivatizedDllName_U(OriginalName, &RealName, &LocalName); 834 if (!NT_SUCCESS(Status)) 835 { 836 DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName, Status); 837 return Status; 838 } 839 840 if (RtlDoesFileExists_UStr(&LocalName)) 841 { 842 Status = get_buffer(&fullname, LocalName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL); 843 if (NT_SUCCESS(Status)) 844 { 845 RtlCopyMemory(fullname, LocalName.Buffer, LocalName.Length + sizeof(UNICODE_NULL)); 846 } 847 else 848 { 849 DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status); 850 } 851 } 852 else if (RtlDoesFileExists_UStr(&RealName)) 853 { 854 Status = get_buffer(&fullname, RealName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL); 855 if (NT_SUCCESS(Status)) 856 { 857 RtlCopyMemory(fullname, RealName.Buffer, RealName.Length + sizeof(UNICODE_NULL)); 858 } 859 else 860 { 861 DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status); 862 } 863 } 864 else 865 { 866 Status = STATUS_NOT_FOUND; 867 } 868 869 if (RealName.Buffer != RealNameBuf) 870 RtlFreeUnicodeString(&RealName); 871 if (LocalName.Buffer != LocalNameBuf) 872 RtlFreeUnicodeString(&LocalName); 873 874 if (NT_SUCCESS(Status)) 875 { 876 DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname); 877 if (!StaticString || StaticString->Buffer != fullname) 878 { 879 RtlInitUnicodeString(DynamicString, fullname); 880 *NewName = DynamicString; 881 } 882 else 883 { 884 *NewName = StaticString; 885 } 886 return Status; 887 } 888 } 889 890 pstrParam = OriginalName; 891 892 /* Get the file name with an extension */ 893 p = OriginalName->Buffer + OriginalName->Length / sizeof(WCHAR) - 1; 894 GotExtension = FALSE; 895 while (p >= OriginalName->Buffer) 896 { 897 c = *p--; 898 if (c == L'.') 899 { 900 GotExtension = TRUE; 901 } 902 else if (c == L'\\') 903 { 904 localStr.Buffer = p + 2; 905 localStr.Length = OriginalName->Length - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer); 906 localStr.MaximumLength = OriginalName->MaximumLength - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer); 907 pstrParam = &localStr; 908 break; 909 } 910 } 911 912 if (!GotExtension) 913 { 914 if (!Extension) 915 { 916 return STATUS_SXS_KEY_NOT_FOUND; 917 } 918 919 if (pstrParam->Length + Extension->Length > sizeof(buffer)) 920 { 921 //FIXME! 922 return STATUS_NO_MEMORY; 923 } 924 925 RtlInitEmptyUnicodeString(&localStr2, buffer, sizeof(buffer)); 926 RtlAppendUnicodeStringToString(&localStr2, pstrParam); 927 RtlAppendUnicodeStringToString(&localStr2, Extension); 928 pstrParam = &localStr2; 929 } 930 931 /* Use wine's function as long as we use wine's sxs implementation in ntdll */ 932 Status = find_actctx_dll(pstrParam, &fullname, StaticString, DynamicString != NULL); 933 if (!NT_SUCCESS(Status)) 934 { 935 return Status; 936 } 937 938 DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname); 939 940 if (!StaticString || StaticString->Buffer != fullname) 941 { 942 RtlInitUnicodeString(DynamicString, fullname); 943 *NewName = DynamicString; 944 } 945 else 946 { 947 *NewName = StaticString; 948 } 949 950 return Status; 951 } 952 953 /* 954 * @implemented 955 */ 956 NTSYSAPI 957 NTSTATUS 958 NTAPI 959 RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection) 960 { 961 /* This is what Windows returns on x86 */ 962 return STATUS_NOT_IMPLEMENTED; 963 } 964 965 /* 966 * @implemented 967 */ 968 NTSYSAPI 969 NTSTATUS 970 NTAPI 971 RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection, 972 OUT PVOID *OldFsRedirectionLevel) 973 { 974 /* This is what Windows returns on x86 */ 975 return STATUS_NOT_IMPLEMENTED; 976 } 977 978 /* 979 * @unimplemented 980 */ 981 NTSYSAPI 982 NTSTATUS 983 NTAPI 984 RtlComputeImportTableHash(IN HANDLE FileHandle, 985 OUT PCHAR Hash, 986 IN ULONG ImportTableHashSize) 987 { 988 UNIMPLEMENTED; 989 return STATUS_NOT_IMPLEMENTED; 990 } 991 992 NTSTATUS 993 NTAPI 994 RtlpSafeCopyMemory( 995 _Out_writes_bytes_all_(Length) VOID UNALIGNED *Destination, 996 _In_reads_bytes_(Length) CONST VOID UNALIGNED *Source, 997 _In_ SIZE_T Length) 998 { 999 _SEH2_TRY 1000 { 1001 RtlCopyMemory(Destination, Source, Length); 1002 } 1003 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1004 { 1005 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 1006 } 1007 _SEH2_END; 1008 1009 return STATUS_SUCCESS; 1010 } 1011 1012 /* FIXME: code duplication with kernel32/client/time.c */ 1013 ULONG 1014 NTAPI 1015 RtlGetTickCount(VOID) 1016 { 1017 ULARGE_INTEGER TickCount; 1018 1019 #ifdef _WIN64 1020 TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount); 1021 #else 1022 while (TRUE) 1023 { 1024 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time; 1025 TickCount.LowPart = SharedUserData->TickCount.LowPart; 1026 1027 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) 1028 break; 1029 1030 YieldProcessor(); 1031 } 1032 #endif 1033 1034 return (ULONG)((UInt32x32To64(TickCount.LowPart, 1035 SharedUserData->TickCountMultiplier) >> 24) + 1036 UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF, 1037 SharedUserData->TickCountMultiplier)); 1038 } 1039 1040 /* EOF */ 1041