ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ldrpe.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.