Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenldrpe.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: lib/ntdll/ldr/ldrpe.c 00005 * PURPOSE: Loader Functions dealing low-level PE Format structures 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntdll.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 PVOID LdrpManifestProberRoutine; 00018 ULONG LdrpNormalSnap; 00019 00020 /* FUNCTIONS *****************************************************************/ 00021 00022 VOID 00023 NTAPI 00024 AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 00025 { 00026 /* Check if page heap dll notification is turned on */ 00027 if (!(RtlpDphGlobalFlags & DPH_FLAG_DLL_NOTIFY)) 00028 return; 00029 00030 /* We don't support this flag currently */ 00031 UNIMPLEMENTED; 00032 } 00033 00034 NTSTATUS 00035 NTAPI 00036 LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, 00037 IN PLDR_DATA_TABLE_ENTRY ImportLdrEntry, 00038 IN PIMAGE_IMPORT_DESCRIPTOR IatEntry, 00039 IN BOOLEAN EntriesValid) 00040 { 00041 PVOID Iat; 00042 NTSTATUS Status; 00043 PIMAGE_THUNK_DATA OriginalThunk, FirstThunk; 00044 PIMAGE_NT_HEADERS NtHeader; 00045 PIMAGE_SECTION_HEADER SectionHeader; 00046 PIMAGE_EXPORT_DIRECTORY ExportDirectory; 00047 LPSTR ImportName; 00048 ULONG ForwarderChain, i, Rva, OldProtect, IatSize, ExportSize; 00049 SIZE_T ImportSize; 00050 DPRINT("LdrpSnapIAT(%wZ %wZ %p %d)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid); 00051 00052 /* Get export directory */ 00053 ExportDirectory = RtlImageDirectoryEntryToData(ExportLdrEntry->DllBase, 00054 TRUE, 00055 IMAGE_DIRECTORY_ENTRY_EXPORT, 00056 &ExportSize); 00057 00058 /* Make sure it has one */ 00059 if (!ExportDirectory) 00060 { 00061 /* Fail */ 00062 DbgPrint("LDR: %wZ doesn't contain an EXPORT table\n", 00063 &ExportLdrEntry->BaseDllName); 00064 return STATUS_INVALID_IMAGE_FORMAT; 00065 } 00066 00067 /* Get the IAT */ 00068 Iat = RtlImageDirectoryEntryToData(ImportLdrEntry->DllBase, 00069 TRUE, 00070 IMAGE_DIRECTORY_ENTRY_IAT, 00071 &IatSize); 00072 ImportSize = IatSize; 00073 00074 /* Check if we don't have one */ 00075 if (!Iat) 00076 { 00077 /* Get the NT Header and the first section */ 00078 NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase); 00079 if (!NtHeader) return STATUS_INVALID_IMAGE_FORMAT; 00080 SectionHeader = IMAGE_FIRST_SECTION(NtHeader); 00081 00082 /* Get the RVA of the import directory */ 00083 Rva = NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 00084 00085 /* Make sure we got one */ 00086 if (Rva) 00087 { 00088 /* Loop all the sections */ 00089 for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++) 00090 { 00091 /* Check if we are inside this section */ 00092 if ((Rva >= SectionHeader->VirtualAddress) && 00093 (Rva < (SectionHeader->VirtualAddress + 00094 SectionHeader->SizeOfRawData))) 00095 { 00096 /* We are, so set the IAT here */ 00097 Iat = (PVOID)((ULONG_PTR)(ImportLdrEntry->DllBase) + 00098 SectionHeader->VirtualAddress); 00099 00100 /* Set the size */ 00101 IatSize = SectionHeader->Misc.VirtualSize; 00102 00103 /* Deal with Watcom and other retarded compilers */ 00104 if (!IatSize) IatSize = SectionHeader->SizeOfRawData; 00105 00106 /* Found it, get out */ 00107 break; 00108 } 00109 00110 /* No match, move to the next section */ 00111 SectionHeader++; 00112 } 00113 } 00114 00115 /* If we still don't have an IAT, that's bad */ 00116 if (!Iat) 00117 { 00118 /* Fail */ 00119 DbgPrint("LDR: Unable to unprotect IAT for %wZ (Image Base %p)\n", 00120 &ImportLdrEntry->BaseDllName, 00121 ImportLdrEntry->DllBase); 00122 return STATUS_INVALID_IMAGE_FORMAT; 00123 } 00124 00125 /* Set the right size */ 00126 ImportSize = IatSize; 00127 } 00128 00129 /* Unprotect the IAT */ 00130 Status = NtProtectVirtualMemory(NtCurrentProcess(), 00131 &Iat, 00132 &ImportSize, 00133 PAGE_READWRITE, 00134 &OldProtect); 00135 if (!NT_SUCCESS(Status)) 00136 { 00137 /* Fail */ 00138 DbgPrint("LDR: Unable to unprotect IAT for %wZ (Status %x)\n", 00139 &ImportLdrEntry->BaseDllName, 00140 Status); 00141 return Status; 00142 } 00143 00144 /* Check if the Thunks are already valid */ 00145 if (EntriesValid) 00146 { 00147 /* We'll only do forwarders. Get the import name */ 00148 ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase + IatEntry->Name); 00149 00150 /* Get the list of forwaders */ 00151 ForwarderChain = IatEntry->ForwarderChain; 00152 00153 /* Loop them */ 00154 while (ForwarderChain != -1) 00155 { 00156 /* Get the cached thunk VA*/ 00157 OriginalThunk = (PIMAGE_THUNK_DATA) 00158 ((ULONG_PTR)ImportLdrEntry->DllBase + 00159 IatEntry->OriginalFirstThunk + 00160 (ForwarderChain * sizeof(IMAGE_THUNK_DATA))); 00161 00162 /* Get the first thunk */ 00163 FirstThunk = (PIMAGE_THUNK_DATA) 00164 ((ULONG_PTR)ImportLdrEntry->DllBase + 00165 IatEntry->FirstThunk + 00166 (ForwarderChain * sizeof(IMAGE_THUNK_DATA))); 00167 00168 /* Get the Forwarder from the thunk */ 00169 ForwarderChain = (ULONG)FirstThunk->u1.Ordinal; 00170 00171 /* Snap the thunk */ 00172 _SEH2_TRY 00173 { 00174 Status = LdrpSnapThunk(ExportLdrEntry->DllBase, 00175 ImportLdrEntry->DllBase, 00176 OriginalThunk, 00177 FirstThunk, 00178 ExportDirectory, 00179 ExportSize, 00180 TRUE, 00181 ImportName); 00182 00183 /* Move to the next thunk */ 00184 FirstThunk++; 00185 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00186 { 00187 /* Fail with the SEH error */ 00188 Status = _SEH2_GetExceptionCode(); 00189 } _SEH2_END; 00190 00191 /* If we messed up, exit */ 00192 if (!NT_SUCCESS(Status)) break; 00193 } 00194 } 00195 else if (IatEntry->FirstThunk) 00196 { 00197 /* Full snapping. Get the First thunk */ 00198 FirstThunk = (PIMAGE_THUNK_DATA) 00199 ((ULONG_PTR)ImportLdrEntry->DllBase + 00200 IatEntry->FirstThunk); 00201 00202 /* Get the NT Header */ 00203 NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase); 00204 00205 /* Get the Original thunk VA, watch out for weird images */ 00206 if ((IatEntry->Characteristics < NtHeader->OptionalHeader.SizeOfHeaders) || 00207 (IatEntry->Characteristics >= NtHeader->OptionalHeader.SizeOfImage)) 00208 { 00209 /* Refuse it, this is a strange linked file */ 00210 OriginalThunk = FirstThunk; 00211 } 00212 else 00213 { 00214 /* Get the address from the field and convert to VA */ 00215 OriginalThunk = (PIMAGE_THUNK_DATA) 00216 ((ULONG_PTR)ImportLdrEntry->DllBase + 00217 IatEntry->OriginalFirstThunk); 00218 } 00219 00220 /* Get the Import name VA */ 00221 ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase + 00222 IatEntry->Name); 00223 00224 /* Loop while it's valid */ 00225 while (OriginalThunk->u1.AddressOfData) 00226 { 00227 /* Snap the Thunk */ 00228 _SEH2_TRY 00229 { 00230 Status = LdrpSnapThunk(ExportLdrEntry->DllBase, 00231 ImportLdrEntry->DllBase, 00232 OriginalThunk, 00233 FirstThunk, 00234 ExportDirectory, 00235 ExportSize, 00236 TRUE, 00237 ImportName); 00238 00239 /* Next thunks */ 00240 OriginalThunk++; 00241 FirstThunk++; 00242 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00243 { 00244 /* Fail with the SEH error */ 00245 Status = _SEH2_GetExceptionCode(); 00246 } _SEH2_END; 00247 00248 /* If we failed the snap, break out */ 00249 if (!NT_SUCCESS(Status)) break; 00250 } 00251 } 00252 00253 /* Protect the IAT again */ 00254 NtProtectVirtualMemory(NtCurrentProcess(), 00255 &Iat, 00256 &ImportSize, 00257 OldProtect, 00258 &OldProtect); 00259 00260 /* Also flush out the cache */ 00261 NtFlushInstructionCache(NtCurrentProcess(), Iat, IatSize); 00262 00263 /* Return to Caller */ 00264 return Status; 00265 } 00266 00267 NTSTATUS 00268 NTAPI 00269 LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, 00270 IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00271 IN PIMAGE_BOUND_IMPORT_DESCRIPTOR *BoundEntryPtr, 00272 IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry) 00273 { 00274 LPSTR ImportName = NULL, BoundImportName, ForwarderName; 00275 NTSTATUS Status; 00276 BOOLEAN AlreadyLoaded = FALSE, Stale; 00277 PIMAGE_IMPORT_DESCRIPTOR ImportEntry; 00278 PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry; 00279 PIMAGE_BOUND_FORWARDER_REF ForwarderEntry; 00280 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry; 00281 PPEB Peb = NtCurrentPeb(); 00282 ULONG i, IatSize; 00283 00284 /* Get the pointer to the bound entry */ 00285 BoundEntry = *BoundEntryPtr; 00286 00287 /* Get the name's VA */ 00288 BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName; 00289 00290 /* Show debug mesage */ 00291 if (ShowSnaps) 00292 { 00293 DPRINT1("LDR: %wZ bound to %s\n", &LdrEntry->BaseDllName, BoundImportName); 00294 } 00295 00296 /* Load the module for this entry */ 00297 Status = LdrpLoadImportModule(DllPath, 00298 BoundImportName, 00299 LdrEntry->DllBase, 00300 &DllLdrEntry, 00301 &AlreadyLoaded); 00302 if (!NT_SUCCESS(Status)) 00303 { 00304 /* Show debug message */ 00305 if (ShowSnaps) 00306 { 00307 DPRINT1("LDR: %wZ failed to load import module %s; status = %x\n", 00308 &LdrEntry->BaseDllName, 00309 BoundImportName, 00310 Status); 00311 } 00312 goto Quickie; 00313 } 00314 00315 /* Check if it wasn't already loaded */ 00316 if (!AlreadyLoaded) 00317 { 00318 /* Add it to our list */ 00319 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 00320 &DllLdrEntry->InInitializationOrderModuleList); 00321 } 00322 00323 /* Check if the Bound Entry is now invalid */ 00324 if ((BoundEntry->TimeDateStamp != DllLdrEntry->TimeDateStamp) || 00325 (DllLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE)) 00326 { 00327 /* Show debug message */ 00328 if (ShowSnaps) 00329 { 00330 DPRINT1("LDR: %wZ has stale binding to %s\n", 00331 &LdrEntry->BaseDllName, 00332 BoundImportName); 00333 } 00334 00335 /* Remember it's become stale */ 00336 Stale = TRUE; 00337 } 00338 else 00339 { 00340 /* Show debug message */ 00341 if (ShowSnaps) 00342 { 00343 DPRINT1("LDR: %wZ has correct binding to %s\n", 00344 &LdrEntry->BaseDllName, 00345 BoundImportName); 00346 } 00347 00348 /* Remember it's valid */ 00349 Stale = FALSE; 00350 } 00351 00352 /* Get the forwarders */ 00353 ForwarderEntry = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1); 00354 00355 /* Loop them */ 00356 for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++) 00357 { 00358 /* Get the name */ 00359 ForwarderName = (LPSTR)FirstEntry + ForwarderEntry->OffsetModuleName; 00360 00361 /* Show debug message */ 00362 if (ShowSnaps) 00363 { 00364 DPRINT1("LDR: %wZ bound to %s via forwarder(s) from %wZ\n", 00365 &LdrEntry->BaseDllName, 00366 ForwarderName, 00367 &DllLdrEntry->BaseDllName); 00368 } 00369 00370 /* Load the module */ 00371 Status = LdrpLoadImportModule(DllPath, 00372 ForwarderName, 00373 LdrEntry->DllBase, 00374 &ForwarderLdrEntry, 00375 &AlreadyLoaded); 00376 if (NT_SUCCESS(Status)) 00377 { 00378 /* Loaded it, was it already loaded? */ 00379 if (!AlreadyLoaded) 00380 { 00381 /* Add it to our list */ 00382 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 00383 &ForwarderLdrEntry->InInitializationOrderModuleList); 00384 } 00385 } 00386 00387 /* Check if the Bound Entry is now invalid */ 00388 if (!(NT_SUCCESS(Status)) || 00389 (ForwarderEntry->TimeDateStamp != ForwarderLdrEntry->TimeDateStamp) || 00390 (ForwarderLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE)) 00391 { 00392 /* Show debug message */ 00393 if (ShowSnaps) 00394 { 00395 DPRINT1("LDR: %wZ has stale binding to %s\n", 00396 &LdrEntry->BaseDllName, 00397 ForwarderName); 00398 } 00399 00400 /* Remember it's become stale */ 00401 Stale = TRUE; 00402 } 00403 else 00404 { 00405 /* Show debug message */ 00406 if (ShowSnaps) 00407 { 00408 DPRINT1("LDR: %wZ has correct binding to %s\n", 00409 &LdrEntry->BaseDllName, 00410 ForwarderName); 00411 } 00412 00413 /* Remember it's valid */ 00414 Stale = FALSE; 00415 } 00416 00417 /* Move to the next one */ 00418 ForwarderEntry++; 00419 } 00420 00421 /* Set the next bound entry to the forwarder */ 00422 FirstEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)ForwarderEntry; 00423 00424 /* Check if the binding was stale */ 00425 if (Stale) 00426 { 00427 /* It was, so find the IAT entry for it */ 00428 ++LdrpNormalSnap; 00429 ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 00430 TRUE, 00431 IMAGE_DIRECTORY_ENTRY_IMPORT, 00432 &IatSize); 00433 00434 /* Make sure it has a name */ 00435 while (ImportEntry->Name) 00436 { 00437 /* Get the name */ 00438 ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name); 00439 00440 /* Compare it */ 00441 if (!_stricmp(ImportName, BoundImportName)) break; 00442 00443 /* Move to next entry */ 00444 ImportEntry++; 00445 } 00446 00447 /* If we didn't find a name, fail */ 00448 if (!ImportEntry->Name) 00449 { 00450 /* Show debug message */ 00451 if (ShowSnaps) 00452 { 00453 DPRINT1("LDR: LdrpWalkImportTable - failing with" 00454 "STATUS_OBJECT_NAME_INVALID due to no import descriptor name\n"); 00455 } 00456 00457 /* Return error */ 00458 Status = STATUS_OBJECT_NAME_INVALID; 00459 goto Quickie; 00460 } 00461 00462 /* Show debug message */ 00463 if (ShowSnaps) 00464 { 00465 DPRINT1("LDR: Stale Bind %s from %wZ\n", 00466 ImportName, 00467 &LdrEntry->BaseDllName); 00468 } 00469 00470 /* Snap the IAT Entry*/ 00471 Status = LdrpSnapIAT(DllLdrEntry, 00472 LdrEntry, 00473 ImportEntry, 00474 FALSE); 00475 00476 /* Make sure we didn't fail */ 00477 if (!NT_SUCCESS(Status)) 00478 { 00479 /* Show debug message */ 00480 if (ShowSnaps) 00481 { 00482 DPRINT1("LDR: %wZ failed to load import module %s; status = %x\n", 00483 &LdrEntry->BaseDllName, 00484 BoundImportName, 00485 Status); 00486 } 00487 00488 /* Return */ 00489 goto Quickie; 00490 } 00491 } 00492 00493 /* All done */ 00494 Status = STATUS_SUCCESS; 00495 00496 Quickie: 00497 /* Write where we are now and return */ 00498 *BoundEntryPtr = FirstEntry; 00499 return Status; 00500 } 00501 00502 NTSTATUS 00503 NTAPI 00504 LdrpHandleNewFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL, 00505 IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00506 IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry) 00507 { 00508 PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry = BoundEntry; 00509 NTSTATUS Status; 00510 00511 /* Make sure we have a name */ 00512 while (BoundEntry->OffsetModuleName) 00513 { 00514 /* Parse this descriptor */ 00515 Status = LdrpHandleOneNewFormatImportDescriptor(DllPath, 00516 LdrEntry, 00517 &BoundEntry, 00518 FirstEntry); 00519 if (!NT_SUCCESS(Status)) return Status; 00520 } 00521 00522 /* Done */ 00523 return STATUS_SUCCESS; 00524 } 00525 00526 NTSTATUS 00527 NTAPI 00528 LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, 00529 IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00530 IN PIMAGE_IMPORT_DESCRIPTOR *ImportEntry) 00531 { 00532 LPSTR ImportName; 00533 NTSTATUS Status; 00534 BOOLEAN AlreadyLoaded = FALSE; 00535 PLDR_DATA_TABLE_ENTRY DllLdrEntry; 00536 PIMAGE_THUNK_DATA FirstThunk; 00537 PPEB Peb = NtCurrentPeb(); 00538 00539 /* Get the import name's VA */ 00540 ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + (*ImportEntry)->Name); 00541 00542 /* Get the first thunk */ 00543 FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + 00544 (*ImportEntry)->FirstThunk); 00545 00546 /* Make sure it's valid */ 00547 if (!FirstThunk->u1.Function) goto SkipEntry; 00548 00549 /* Show debug message */ 00550 if (ShowSnaps) 00551 { 00552 DPRINT1("LDR: %s used by %wZ\n", 00553 ImportName, 00554 &LdrEntry->BaseDllName); 00555 } 00556 00557 /* Load the module associated to it */ 00558 Status = LdrpLoadImportModule(DllPath, 00559 ImportName, 00560 LdrEntry->DllBase, 00561 &DllLdrEntry, 00562 &AlreadyLoaded); 00563 if (!NT_SUCCESS(Status)) 00564 { 00565 /* Fail */ 00566 if (ShowSnaps) 00567 { 00568 DbgPrint("LDR: LdrpWalkImportTable - LdrpLoadImportModule failed " 00569 "on import %s with status %x\n", 00570 ImportName, 00571 Status); 00572 } 00573 00574 /* Return */ 00575 return Status; 00576 } 00577 00578 /* Show debug message */ 00579 if (ShowSnaps) 00580 { 00581 DPRINT1("LDR: Snapping imports for %wZ from %s\n", 00582 &LdrEntry->BaseDllName, 00583 ImportName); 00584 } 00585 00586 /* Check if it wasn't already loaded */ 00587 ++LdrpNormalSnap; 00588 if (!AlreadyLoaded) 00589 { 00590 /* Add the DLL to our list */ 00591 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 00592 &DllLdrEntry->InInitializationOrderModuleList); 00593 } 00594 00595 /* Now snap the IAT Entry */ 00596 Status = LdrpSnapIAT(DllLdrEntry, LdrEntry, *ImportEntry, FALSE); 00597 if (!NT_SUCCESS(Status)) 00598 { 00599 /* Fail */ 00600 if (ShowSnaps) 00601 { 00602 DbgPrint("LDR: LdrpWalkImportTable - LdrpSnapIAT #2 failed with " 00603 "status %x\n", 00604 Status); 00605 } 00606 00607 /* Return */ 00608 return Status; 00609 } 00610 00611 SkipEntry: 00612 /* Move on */ 00613 (*ImportEntry)++; 00614 return STATUS_SUCCESS; 00615 } 00616 00617 NTSTATUS 00618 NTAPI 00619 LdrpHandleOldFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL, 00620 IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00621 IN PIMAGE_IMPORT_DESCRIPTOR ImportEntry) 00622 { 00623 NTSTATUS Status; 00624 00625 /* Check for Name and Thunk */ 00626 while ((ImportEntry->Name) && (ImportEntry->FirstThunk)) 00627 { 00628 /* Parse this descriptor */ 00629 Status = LdrpHandleOneOldFormatImportDescriptor(DllPath, 00630 LdrEntry, 00631 &ImportEntry); 00632 if (!NT_SUCCESS(Status)) return Status; 00633 } 00634 00635 /* Done */ 00636 return STATUS_SUCCESS; 00637 } 00638 00639 USHORT 00640 NTAPI 00641 LdrpNameToOrdinal(IN LPSTR ImportName, 00642 IN ULONG NumberOfNames, 00643 IN PVOID ExportBase, 00644 IN PULONG NameTable, 00645 IN PUSHORT OrdinalTable) 00646 { 00647 LONG Start, End, Next, CmpResult; 00648 00649 /* Use classical binary search to find the ordinal */ 00650 Start = Next = 0; 00651 End = NumberOfNames - 1; 00652 while (End >= Start) 00653 { 00654 /* Next will be exactly between Start and End */ 00655 Next = (Start + End) >> 1; 00656 00657 /* Compare this name with the one we need to find */ 00658 CmpResult = strcmp(ImportName, (PCHAR)((ULONG_PTR)ExportBase + NameTable[Next])); 00659 00660 /* We found our entry if result is 0 */ 00661 if (!CmpResult) break; 00662 00663 /* We didn't find, update our range then */ 00664 if (CmpResult < 0) 00665 { 00666 End = Next - 1; 00667 } 00668 else if (CmpResult > 0) 00669 { 00670 Start = Next + 1; 00671 } 00672 } 00673 00674 /* If end is before start, then the search failed */ 00675 if (End < Start) return -1; 00676 00677 /* Return found name */ 00678 return OrdinalTable[Next]; 00679 } 00680 00681 NTSTATUS 00682 NTAPI 00683 LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, 00684 IN PLDR_DATA_TABLE_ENTRY LdrEntry) 00685 { 00686 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 00687 PPEB Peb = NtCurrentPeb(); 00688 NTSTATUS Status = STATUS_SUCCESS; 00689 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL; 00690 PIMAGE_IMPORT_DESCRIPTOR ImportEntry; 00691 ULONG BoundSize, IatSize; 00692 DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry); 00693 00694 /* Set up the Act Ctx */ 00695 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 00696 ActCtx.Size = sizeof(ActCtx); 00697 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 00698 00699 /* Check if we have a manifest prober routine */ 00700 if (LdrpManifestProberRoutine) 00701 { 00702 DPRINT1("We don't support manifests yet, much less prober routines\n"); 00703 } 00704 00705 /* Check if we failed above */ 00706 if (!NT_SUCCESS(Status)) return Status; 00707 00708 /* Get the Active ActCtx */ 00709 Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext); 00710 if (!NT_SUCCESS(Status)) 00711 { 00712 /* Exit */ 00713 DbgPrintEx(51, // DPFLTR_SXS_ID 00714 DPFLTR_WARNING_LEVEL, 00715 "LDR: RtlGetActiveActivationContext() failed; ntstatus = " 00716 "0x%08lx\n", 00717 Status); 00718 return Status; 00719 } 00720 00721 /* Activate the ActCtx */ 00722 RtlActivateActivationContextUnsafeFast(&ActCtx, 00723 LdrEntry->EntryPointActivationContext); 00724 00725 /* Check if we were redirected */ 00726 if (!(LdrEntry->Flags & LDRP_REDIRECTED)) 00727 { 00728 /* Get the Bound IAT */ 00729 BoundEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 00730 TRUE, 00731 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, 00732 &BoundSize); 00733 } 00734 00735 /* Get the regular IAT, for fallback */ 00736 ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 00737 TRUE, 00738 IMAGE_DIRECTORY_ENTRY_IMPORT, 00739 &IatSize); 00740 00741 /* Check if we got at least one */ 00742 if ((BoundEntry) || (ImportEntry)) 00743 { 00744 /* Do we have a Bound IAT */ 00745 if (BoundEntry) 00746 { 00747 /* Handle the descriptor */ 00748 Status = LdrpHandleNewFormatImportDescriptors(DllPath, 00749 LdrEntry, 00750 BoundEntry); 00751 } 00752 else 00753 { 00754 /* Handle the descriptor */ 00755 Status = LdrpHandleOldFormatImportDescriptors(DllPath, 00756 LdrEntry, 00757 ImportEntry); 00758 } 00759 00760 /* Check the status of the handlers */ 00761 if (NT_SUCCESS(Status)) 00762 { 00763 /* Check for Per-DLL Heap Tagging */ 00764 if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAG_BY_DLL) 00765 { 00766 /* FIXME */ 00767 DPRINT1("We don't support Per-DLL Heap Tagging yet!\n"); 00768 } 00769 00770 /* Check if Page Heap was enabled */ 00771 if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) 00772 { 00773 /* Initialize target DLL */ 00774 AVrfPageHeapDllNotification(LdrEntry); 00775 } 00776 00777 /* Check if Application Verifier was enabled */ 00778 if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK) 00779 { 00780 /* FIXME */ 00781 DPRINT1("We don't support Application Verifier yet!\n"); 00782 } 00783 00784 /* Just to be safe */ 00785 Status = STATUS_SUCCESS; 00786 } 00787 } 00788 00789 /* Release the activation context */ 00790 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00791 00792 /* Return status */ 00793 return Status; 00794 } 00795 00796 /* FIXME: This function is missing SxS support and has wrong prototype */ 00797 NTSTATUS 00798 NTAPI 00799 LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, 00800 IN LPSTR ImportName, 00801 IN PVOID DllBase, 00802 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry, 00803 OUT PBOOLEAN Existing) 00804 { 00805 ANSI_STRING AnsiString; 00806 PUNICODE_STRING ImpDescName; 00807 NTSTATUS Status; 00808 PPEB Peb = RtlGetCurrentPeb(); 00809 PTEB Teb = NtCurrentTeb(); 00810 00811 DPRINT("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing); 00812 00813 /* Convert import descriptor name to unicode string */ 00814 ImpDescName = &Teb->StaticUnicodeString; 00815 RtlInitAnsiString(&AnsiString, ImportName); 00816 Status = RtlAnsiStringToUnicodeString(ImpDescName, &AnsiString, FALSE); 00817 if (!NT_SUCCESS(Status)) return Status; 00818 00819 /* Check if it's loaded */ 00820 if (LdrpCheckForLoadedDll(DllPath, 00821 ImpDescName, 00822 TRUE, 00823 FALSE, 00824 DataTableEntry)) 00825 { 00826 /* It's already existing in the list */ 00827 *Existing = TRUE; 00828 return STATUS_SUCCESS; 00829 } 00830 00831 /* We're loading it for the first time */ 00832 *Existing = FALSE; 00833 00834 /* Map it */ 00835 Status = LdrpMapDll(DllPath, 00836 NULL, 00837 ImpDescName->Buffer, 00838 NULL, 00839 TRUE, 00840 FALSE, 00841 DataTableEntry); 00842 00843 if (!NT_SUCCESS(Status)) return Status; 00844 00845 /* Walk its import descriptor table */ 00846 Status = LdrpWalkImportDescriptor(DllPath, 00847 *DataTableEntry); 00848 if (!NT_SUCCESS(Status)) 00849 { 00850 /* Add it to the in-init-order list in case of failure */ 00851 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 00852 &(*DataTableEntry)->InInitializationOrderModuleList); 00853 } 00854 00855 return Status; 00856 } 00857 00858 NTSTATUS 00859 NTAPI 00860 LdrpSnapThunk(IN PVOID ExportBase, 00861 IN PVOID ImportBase, 00862 IN PIMAGE_THUNK_DATA OriginalThunk, 00863 IN OUT PIMAGE_THUNK_DATA Thunk, 00864 IN PIMAGE_EXPORT_DIRECTORY ExportEntry, 00865 IN ULONG ExportSize, 00866 IN BOOLEAN Static, 00867 IN LPSTR DllName) 00868 { 00869 BOOLEAN IsOrdinal; 00870 USHORT Ordinal; 00871 ULONG OriginalOrdinal = 0; 00872 PIMAGE_IMPORT_BY_NAME AddressOfData; 00873 PULONG NameTable; 00874 PUSHORT OrdinalTable; 00875 LPSTR ImportName = NULL; 00876 USHORT Hint; 00877 NTSTATUS Status; 00878 ULONG_PTR HardErrorParameters[3]; 00879 UNICODE_STRING HardErrorDllName, HardErrorEntryPointName; 00880 ANSI_STRING TempString; 00881 ULONG Mask; 00882 ULONG Response; 00883 PULONG AddressOfFunctions; 00884 UNICODE_STRING TempUString; 00885 ANSI_STRING ForwarderName; 00886 PANSI_STRING ForwardName; 00887 PVOID ForwarderHandle; 00888 ULONG ForwardOrdinal; 00889 00890 /* Check if the snap is by ordinal */ 00891 if ((IsOrdinal = IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal))) 00892 { 00893 /* Get the ordinal number, and its normalized version */ 00894 OriginalOrdinal = IMAGE_ORDINAL(OriginalThunk->u1.Ordinal); 00895 Ordinal = (USHORT)(OriginalOrdinal - ExportEntry->Base); 00896 } 00897 else 00898 { 00899 /* First get the data VA */ 00900 AddressOfData = (PIMAGE_IMPORT_BY_NAME) 00901 ((ULONG_PTR)ImportBase + 00902 ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xffffffff)); 00903 00904 /* Get the name */ 00905 ImportName = (LPSTR)AddressOfData->Name; 00906 00907 /* Now get the VA of the Name and Ordinal Tables */ 00908 NameTable = (PULONG)((ULONG_PTR)ExportBase + 00909 (ULONG_PTR)ExportEntry->AddressOfNames); 00910 OrdinalTable = (PUSHORT)((ULONG_PTR)ExportBase + 00911 (ULONG_PTR)ExportEntry->AddressOfNameOrdinals); 00912 00913 /* Get the hint */ 00914 Hint = AddressOfData->Hint; 00915 00916 /* Try to get a match by using the hint */ 00917 if (((ULONG)Hint < ExportEntry->NumberOfNames) && 00918 (!strcmp(ImportName, ((LPSTR)((ULONG_PTR)ExportBase + NameTable[Hint]))))) 00919 { 00920 /* We got a match, get the Ordinal from the hint */ 00921 Ordinal = OrdinalTable[Hint]; 00922 } 00923 else 00924 { 00925 /* Well bummer, hint didn't work, do it the long way */ 00926 Ordinal = LdrpNameToOrdinal(ImportName, 00927 ExportEntry->NumberOfNames, 00928 ExportBase, 00929 NameTable, 00930 OrdinalTable); 00931 } 00932 } 00933 00934 /* Check if the ordinal is invalid */ 00935 if ((ULONG)Ordinal >= ExportEntry->NumberOfFunctions) 00936 { 00937 FailurePath: 00938 /* Is this a static snap? */ 00939 if (Static) 00940 { 00941 /* Inform the debug log */ 00942 if (IsOrdinal) 00943 DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal); 00944 else 00945 DPRINT1("Failed to snap %s\n", ImportName); 00946 00947 /* These are critical errors. Setup a string for the DLL name */ 00948 RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown"); 00949 RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE); 00950 00951 /* Set it as the parameter */ 00952 HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllName; 00953 Mask = 2; 00954 00955 /* Check if we have an ordinal */ 00956 if (IsOrdinal) 00957 { 00958 /* Then set the ordinal as the 1st parameter */ 00959 HardErrorParameters[0] = OriginalOrdinal; 00960 } 00961 else 00962 { 00963 /* We don't, use the entrypoint. Set up a string for it */ 00964 RtlInitAnsiString(&TempString, ImportName); 00965 RtlAnsiStringToUnicodeString(&HardErrorEntryPointName, 00966 &TempString, 00967 TRUE); 00968 00969 /* Set it as the parameter */ 00970 HardErrorParameters[0] = (ULONG_PTR)&HardErrorEntryPointName; 00971 Mask = 3; 00972 } 00973 00974 /* Raise the error */ 00975 NtRaiseHardError(IsOrdinal ? STATUS_ORDINAL_NOT_FOUND : 00976 STATUS_ENTRYPOINT_NOT_FOUND, 00977 2, 00978 Mask, 00979 HardErrorParameters, 00980 OptionOk, 00981 &Response); 00982 00983 /* Increase the error count */ 00984 if (LdrpInLdrInit) LdrpFatalHardErrorCount++; 00985 00986 /* Free our string */ 00987 RtlFreeUnicodeString(&HardErrorDllName); 00988 if (!IsOrdinal) 00989 { 00990 /* Free our second string. Return entrypoint error */ 00991 RtlFreeUnicodeString(&HardErrorEntryPointName); 00992 RtlRaiseStatus(STATUS_ENTRYPOINT_NOT_FOUND); 00993 } 00994 00995 /* Return ordinal error */ 00996 RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND); 00997 } 00998 else 00999 { 01000 /* Inform the debug log */ 01001 if (IsOrdinal) 01002 DPRINT("Non-fatal: Failed to snap ordinal 0x%x\n", OriginalOrdinal); 01003 else 01004 DPRINT("Non-fatal: Failed to snap %s\n", ImportName); 01005 } 01006 01007 /* Set this as a bad DLL */ 01008 Thunk->u1.Function = (ULONG_PTR)0xffbadd11; 01009 01010 /* Return the right error code */ 01011 Status = IsOrdinal ? STATUS_ORDINAL_NOT_FOUND : 01012 STATUS_ENTRYPOINT_NOT_FOUND; 01013 } 01014 else 01015 { 01016 /* The ordinal seems correct, get the AddressOfFunctions VA */ 01017 AddressOfFunctions = (PULONG) 01018 ((ULONG_PTR)ExportBase + 01019 (ULONG_PTR)ExportEntry->AddressOfFunctions); 01020 01021 /* Write the function pointer*/ 01022 Thunk->u1.Function = (ULONG_PTR)ExportBase + AddressOfFunctions[Ordinal]; 01023 01024 /* Make sure it's within the exports */ 01025 if ((Thunk->u1.Function > (ULONG_PTR)ExportEntry) && 01026 (Thunk->u1.Function < ((ULONG_PTR)ExportEntry + ExportSize))) 01027 { 01028 /* Get the Import and Forwarder Names */ 01029 ImportName = (LPSTR)Thunk->u1.Function; 01030 ForwarderName.Buffer = ImportName; 01031 ForwarderName.Length = (USHORT)(strchr(ImportName, '.') - ImportName); 01032 ForwarderName.MaximumLength = ForwarderName.Length; 01033 Status = RtlAnsiStringToUnicodeString(&TempUString, 01034 &ForwarderName, 01035 TRUE); 01036 01037 /* Make sure the conversion was OK */ 01038 if (NT_SUCCESS(Status)) 01039 { 01040 /* Load the forwarder, free the temp string */ 01041 Status = LdrpLoadDll(FALSE, 01042 NULL, 01043 NULL, 01044 &TempUString, 01045 &ForwarderHandle, 01046 FALSE); 01047 RtlFreeUnicodeString(&TempUString); 01048 } 01049 01050 /* If the load or conversion failed, use the failure path */ 01051 if (!NT_SUCCESS(Status)) goto FailurePath; 01052 01053 /* Now set up a name for the actual forwarder dll */ 01054 RtlInitAnsiString(&ForwarderName, 01055 ImportName + ForwarderName.Length + sizeof(CHAR)); 01056 01057 /* Check if it's an ordinal forward */ 01058 if ((ForwarderName.Length > 1) && (*ForwarderName.Buffer == '#')) 01059 { 01060 /* We don't have an actual function name */ 01061 ForwardName = NULL; 01062 01063 /* Convert the string into an ordinal */ 01064 Status = RtlCharToInteger(ForwarderName.Buffer + sizeof(CHAR), 01065 0, 01066 &ForwardOrdinal); 01067 01068 /* If this fails, then error out */ 01069 if (!NT_SUCCESS(Status)) goto FailurePath; 01070 } 01071 else 01072 { 01073 /* Import by name */ 01074 ForwardName = &ForwarderName; 01075 } 01076 01077 /* Get the pointer */ 01078 Status = LdrpGetProcedureAddress(ForwarderHandle, 01079 ForwardName, 01080 ForwardOrdinal, 01081 (PVOID*)&Thunk->u1.Function, 01082 FALSE); 01083 /* If this fails, then error out */ 01084 if (!NT_SUCCESS(Status)) goto FailurePath; 01085 } 01086 else 01087 { 01088 /* It's not within the exports, let's hope it's valid */ 01089 if (!AddressOfFunctions[Ordinal]) goto FailurePath; 01090 } 01091 01092 /* If we got here, then it's success */ 01093 Status = STATUS_SUCCESS; 01094 } 01095 01096 /* Return status */ 01097 return Status; 01098 } 01099 01100 /* EOF */ Generated on Fri May 25 2012 04:20:29 for ReactOS by
1.7.6.1
|