⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: utils.c 25365 2007-01-08 07:43:18Z ion $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS kernel
 * FILE:            lib/ntdll/ldr/utils.c
 * PURPOSE:         Process startup for PE executables
 * PROGRAMMERS:     Jean Michault
 *                  Rex Jolliff (rex@lvcablemodem.com)
 */

/*
 * TODO:
 *      - Handle loading flags correctly
 *      - Handle errors correctly (unload dll's)
 *      - Implement a faster way to find modules (hash table)
 *      - any more ??
 */

/* INCLUDES *****************************************************************/

#include <ntdll.h>
#define NDEBUG
#include <debug.h>

#define LDRP_PROCESS_CREATION_TIME 0x8000000

/* GLOBALS *******************************************************************/

#ifdef NDEBUG
#if defined(__GNUC__)
#define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
#else
#endif	/* __GNUC__ */
#else
#define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
#endif

typedef struct _TLS_DATA
{
   PVOID StartAddressOfRawData;
   DWORD TlsDataSize;
   DWORD TlsZeroSize;
   PIMAGE_TLS_CALLBACK TlsAddressOfCallBacks;
   PLDR_DATA_TABLE_ENTRY Module;
} TLS_DATA, *PTLS_DATA;

static PTLS_DATA LdrpTlsArray = NULL;
static ULONG LdrpTlsCount = 0;
static ULONG LdrpTlsSize = 0;
static HANDLE LdrpKnownDllsDirHandle = NULL;
static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL};
static PLDR_DATA_TABLE_ENTRY LdrpLastModule = NULL;
extern PLDR_DATA_TABLE_ENTRY ExeModule;

/* PROTOTYPES ****************************************************************/

static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_DATA_TABLE_ENTRY *Module, BOOLEAN Ref);
static PVOID LdrFixupForward(PCHAR ForwardName);
static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint);
static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
                               IN ULONG LoadFlags,
                               IN PUNICODE_STRING Name,
                               OUT PLDR_DATA_TABLE_ENTRY *Module,
                               OUT PVOID *BaseAddress OPTIONAL);
static NTSTATUS LdrpAttachProcess(VOID);
static VOID LdrpDetachProcess(BOOLEAN UnloadAll);

/* FUNCTIONS *****************************************************************/

#if defined(DBG) || defined(KDBG)

VOID
LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule)
{
  NtSystemDebugControl(
    SysDbgQueryVersion,
    (PVOID)LdrModule,
    0,
    NULL,
    0,
    NULL);
}

#endif /* DBG || KDBG */

BOOLEAN
LdrMappedAsDataFile(PVOID *BaseAddress)
{
  if (0 != ((DWORD_PTR) *BaseAddress & (PAGE_SIZE - 1)))
    {
      *BaseAddress = (PVOID) ((DWORD_PTR) *BaseAddress & ~ ((DWORD_PTR) PAGE_SIZE - 1));
      return TRUE;
    }

   return FALSE;
}

static __inline LONG LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked)
{
   LONG LoadCount;
   if (!Locked)
     {
       RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
     }
   LoadCount = Module->LoadCount;
   if (Module->LoadCount > 0 && Module->LoadCount != 0xFFFF)
     {
       Module->LoadCount--;
     }
   if (!Locked)
     {
       RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
     }
   return LoadCount;
}

static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked)
{
   LONG LoadCount;
   if (!Locked)
     {
       RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
     }
   LoadCount = Module->LoadCount;
   if (Module->LoadCount != 0xFFFF)
     {
       Module->LoadCount++;
     }
   if (!Locked)
     {
       RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
     }
   return LoadCount;
}

static __inline VOID LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module, ULONG Size, BOOLEAN Locked)
{
   if (!Locked)
     {
       RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
     }
   Module->TlsIndex = (SHORT)LdrpTlsCount;
   LdrpTlsCount++;
   LdrpTlsSize += Size;
   if (!Locked)
     {
       RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
     }
}

static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReason)
{
   PIMAGE_TLS_CALLBACK TlsCallback;
   if (Module->TlsIndex != 0xFFFF && Module->LoadCount == 0xFFFF)
     {
       TlsCallback = LdrpTlsArray[Module->TlsIndex].TlsAddressOfCallBacks;
       if (TlsCallback)
         {
           while (*TlsCallback)
             {
               TRACE_LDR("%wZ - Calling tls callback at %x\n",
                         &Module->BaseDllName, TlsCallback);
               TlsCallback(Module->DllBase, dwReason, NULL);
               TlsCallback = (PIMAGE_TLS_CALLBACK)((ULONG_PTR)TlsCallback + sizeof(PVOID));
             }
         }
     }
}

static BOOLEAN LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module, DWORD dwReason, PVOID lpReserved)
{
   if (!(Module->Flags & LDRP_IMAGE_DLL) ||
       Module->EntryPoint == 0)
     {
       return TRUE;
     }
   LdrpTlsCallback(Module, dwReason);
   return  ((PDLLMAIN_FUNC)Module->EntryPoint)(Module->DllBase, dwReason, lpReserved);
}

static NTSTATUS
LdrpInitializeTlsForThread(VOID)
{
   PVOID* TlsPointers;
   PTLS_DATA TlsInfo;
   PVOID TlsData;
   ULONG i;
   PTEB Teb = NtCurrentTeb();

   DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule->BaseDllName);

   Teb->StaticUnicodeString.Length = 0;
   Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
   Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;

   if (LdrpTlsCount > 0)
     {
       TlsPointers = RtlAllocateHeap(RtlGetProcessHeap(),
                                     0,
                                     LdrpTlsCount * sizeof(PVOID) + LdrpTlsSize);
       if (TlsPointers == NULL)
         {
           DPRINT1("failed to allocate thread tls data\n");
           return STATUS_NO_MEMORY;
         }

       TlsData = (PVOID)((ULONG_PTR)TlsPointers + LdrpTlsCount * sizeof(PVOID));
       Teb->ThreadLocalStoragePointer = TlsPointers;

       TlsInfo = LdrpTlsArray;
       for (i = 0; i < LdrpTlsCount; i++, TlsInfo++)
         {
           TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo->Module->BaseDllName);
           TlsPointers[i] = TlsData;
           if (TlsInfo->TlsDataSize)
             {
               memcpy(TlsData, TlsInfo->StartAddressOfRawData, TlsInfo->TlsDataSize);
               TlsData = (PVOID)((ULONG_PTR)TlsData + TlsInfo->TlsDataSize);
             }
           if (TlsInfo->TlsZeroSize)
             {
               memset(TlsData, 0, TlsInfo->TlsZeroSize);
               TlsData = (PVOID)((ULONG_PTR)TlsData + TlsInfo->TlsZeroSize);
             }
         }
     }
   DPRINT("LdrpInitializeTlsForThread() done\n");
   return STATUS_SUCCESS;
}

static NTSTATUS
LdrpInitializeTlsForProccess(VOID)
{
   PLIST_ENTRY ModuleListHead;
   PLIST_ENTRY Entry;
   PLDR_DATA_TABLE_ENTRY Module;
   PIMAGE_TLS_DIRECTORY TlsDirectory;
   PTLS_DATA TlsData;
   ULONG Size;

   DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule->BaseDllName);

   if (LdrpTlsCount > 0)
     {
       LdrpTlsArray = RtlAllocateHeap(RtlGetProcessHeap(),
                                      0,
                                      LdrpTlsCount * sizeof(TLS_DATA));
       if (LdrpTlsArray == NULL)
         {
           DPRINT1("Failed to allocate global tls data\n");
           return STATUS_NO_MEMORY;
         }

       ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
       Entry = ModuleListHead->Flink;
       while (Entry != ModuleListHead)
         {
           Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
           if (Module->LoadCount == 0xFFFF &&
               Module->TlsIndex != 0xFFFF)
             {
               TlsDirectory = (PIMAGE_TLS_DIRECTORY)
                                 RtlImageDirectoryEntryToData(Module->DllBase,
                                                              TRUE,
                                                              IMAGE_DIRECTORY_ENTRY_TLS,
                                                              &Size);
               ASSERT(Module->TlsIndex < LdrpTlsCount);
               TlsData = &LdrpTlsArray[Module->TlsIndex];
               TlsData->StartAddressOfRawData = (PVOID)TlsDirectory->StartAddressOfRawData;
               TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
               TlsData->TlsZeroSize = TlsDirectory->SizeOfZeroFill;
               if (TlsDirectory->AddressOfCallBacks)
                 TlsData->TlsAddressOfCallBacks = *(PIMAGE_TLS_CALLBACK*)TlsDirectory->AddressOfCallBacks;
               else
                 TlsData->TlsAddressOfCallBacks = NULL;
               TlsData->Module = Module;
#if 0
               DbgPrint("TLS directory for %wZ\n", &Module->BaseDllName);
               DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory->StartAddressOfRawData);
               DbgPrint("EndAddressOfRawData:   %x\n", TlsDirectory->EndAddressOfRawData);
               DbgPrint("SizeOfRawData:         %d\n", TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
               DbgPrint("AddressOfIndex:        %x\n", TlsDirectory->AddressOfIndex);
               DbgPrint("AddressOfCallBacks:    %x (%x)\n", TlsDirectory->AddressOfCallBacks, *TlsDirectory->AddressOfCallBacks);
               DbgPrint("SizeOfZeroFill:        %d\n", TlsDirectory->SizeOfZeroFill);
               DbgPrint("Characteristics:       %x\n", TlsDirectory->Characteristics);
#endif
               /*
                * FIXME:
                *   Is this region allways writable ?
                */
               *(PULONG)TlsDirectory->AddressOfIndex = Module->TlsIndex;
             }
           Entry = Entry->Flink;
        }
    }
  DPRINT("LdrpInitializeTlsForProccess() done\n");
  return STATUS_SUCCESS;
}

VOID
LdrpInitLoader(VOID)
{
  OBJECT_ATTRIBUTES ObjectAttributes;
  UNICODE_STRING LinkTarget;
  UNICODE_STRING Name;
  HANDLE LinkHandle;
  ULONG Length;
  NTSTATUS Status;

  DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule->BaseDllName);

  /* Get handle to the 'KnownDlls' directory */
  RtlInitUnicodeString(&Name,
                       L"\\KnownDlls");
  InitializeObjectAttributes(&ObjectAttributes,
                             &Name,
                             OBJ_CASE_INSENSITIVE,
                             NULL,
                             NULL);
  Status = NtOpenDirectoryObject(&LdrpKnownDllsDirHandle,
                                 DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
                                 &ObjectAttributes);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
      LdrpKnownDllsDirHandle = NULL;
      return;
    }

  /* Allocate target name string */
  LinkTarget.Length = 0;
  LinkTarget.MaximumLength = MAX_PATH * sizeof(WCHAR);
  LinkTarget.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
                                      0,
                                      MAX_PATH * sizeof(WCHAR));
  if (LinkTarget.Buffer == NULL)
    {
      NtClose(LdrpKnownDllsDirHandle);
      LdrpKnownDllsDirHandle = NULL;
      return;
    }

  RtlInitUnicodeString(&Name,
                       L"KnownDllPath");
  InitializeObjectAttributes(&ObjectAttributes,
                             &Name,
                             OBJ_CASE_INSENSITIVE,
                             LdrpKnownDllsDirHandle,
                             NULL);
  Status = NtOpenSymbolicLinkObject(&LinkHandle,
                                    SYMBOLIC_LINK_ALL_ACCESS,
                                    &ObjectAttributes);
  if (!NT_SUCCESS(Status))
    {
      RtlFreeUnicodeString(&LinkTarget);
      NtClose(LdrpKnownDllsDirHandle);
      LdrpKnownDllsDirHandle = NULL;
      return;
    }

  Status = NtQuerySymbolicLinkObject(LinkHandle,
                                     &LinkTarget,
                                     &Length);
  NtClose(LinkHandle);
  if (!NT_SUCCESS(Status))
    {
      RtlFreeUnicodeString(&LinkTarget);
      NtClose(LdrpKnownDllsDirHandle);
      LdrpKnownDllsDirHandle = NULL;
    }

  RtlCreateUnicodeString(&LdrpKnownDllPath,
                         LinkTarget.Buffer);

  RtlFreeUnicodeString(&LinkTarget);

  DPRINT("LdrpInitLoader() done\n");
}


/***************************************************************************
 * NAME                                                         LOCAL
 *      LdrAdjustDllName
 *
 * DESCRIPTION
 *      Adjusts the name of a dll to a fully qualified name.
 *
 * ARGUMENTS
 *      FullDllName:    Pointer to caller supplied storage for the fully
 *                      qualified dll name.
 *      DllName:        Pointer to the dll name.
 *      BaseName:       TRUE:  Only the file name is passed to FullDllName
 *                      FALSE: The full path is preserved in FullDllName
 *
 * RETURN VALUE
 *      None
 *
 * REVISIONS
 *
 * NOTE
 *      A given path is not affected by the adjustment, but the file
 *      name only:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -