继续前边2贴,现把LOADLIBRARY也一并贴上。

HMODULE __stdcall MyLoadLibraryA(char *szDllName)
{
  void *pFileAddr;//文件隐射基地址
  void *pImageBase;//加载DLL的基地址,作为返回数
  IMAGE_DOS_HEADER *pDosHead;
  IMAGE_OPTIONAL_HEADER *pOPHead;
  IMAGE_FILE_HEADER  *pFileHead;
  DWORD dwSecNum;
  IMAGE_SECTION_HEADER *pSecInfo;
  IMAGE_IMPORT_DESCRIPTOR *pIID;
  LPTHREAD_START_ROUTINE OEP;
  IMAGE_BASE_RELOCATION *pIBR;
  DWORD dwDllRVA;           //实际装载地址与建议装载地址差。
  HANDLE hFile = ::CreateFile(szDllName,GENERIC_READ,0,NULL,OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,NULL);
  if (hFile==INVALID_HANDLE_VALUE)
  {
    AfxMessageBox("Can't open file");
    return 0;
  }
  HANDLE hMaping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
  pFileAddr = MapViewOfFile(hMaping,FILE_MAP_READ,0,0,0);
    
  pDosHead = (IMAGE_DOS_HEADER*)pFileAddr;
  pFileHead = (IMAGE_FILE_HEADER*)(pDosHead->e_lfanew+4 +(DWORD)pFileAddr);
  
  pOPHead = (IMAGE_OPTIONAL_HEADER*)((DWORD)pFileHead + 
    sizeof(_IMAGE_FILE_HEADER));

  //申请内存,建立DLL内存空间,并COPY DLL
  pImageBase = VirtualAlloc(NULL,pOPHead->SizeOfImage,MEM_COMMIT
    ,PAGE_EXECUTE_READWRITE);
  if (pImageBase == NULL)
  {
    AfxMessageBox("分配空间失败");
    return 0;
  }
  dwDllRVA = (DWORD)pImageBase - pOPHead->ImageBase;
  pSecInfo = (IMAGE_SECTION_HEADER*)((DWORD)pOPHead + pFileHead->SizeOfOptionalHeader) ;
  dwSecNum = pFileHead->NumberOfSections;
  //COPY文件头
  DWORD dwFileSize = pOPHead->SizeOfHeaders;
  memcpy(pImageBase,pFileAddr,dwFileSize);
  
  //COPY区段
  for (DWORD i = 0; i < dwSecNum; i++)
  {
    void *des,*sour;
    des = (void*)(pSecInfo->VirtualAddress + (DWORD)pImageBase);
    sour = (void*)(pSecInfo->PointerToRawData + (DWORD)pFileAddr);
    memcpy(des,sour,pSecInfo->Misc.VirtualSize);
    pSecInfo++;    
  }
  OEP = (LPTHREAD_START_ROUTINE)(pOPHead->AddressOfEntryPoint + 
    (DWORD)pImageBase);

    //  修正重定位表。
  pIBR = (IMAGE_BASE_RELOCATION*)(pOPHead->DataDirectory[5].VirtualAddress + (DWORD)pImageBase);
  while (pIBR->VirtualAddress)
  {
    WORD *pTypeOffset = (WORD*)((DWORD)pIBR+ 8);

    for (i = 0; i < pIBR->SizeOfBlock - 8; i += 2)
    {
      //pTypeOffset[i] & 0Xf000 == 0x3000 结果不对,郁闷。
      if (pTypeOffset[i] >>12 == 3)
      {
        DWORD nTmp =((DWORD) pTypeOffset[i]) & 0xfff;
        DWORD *pReloc = (DWORD*)(nTmp +(DWORD) pImageBase + pIBR->VirtualAddress);
         *pReloc = *pReloc + dwDllRVA;        
      }       
    }
    pIBR = (IMAGE_BASE_RELOCATION*)(pIBR->SizeOfBlock + (DWORD)pIBR);
  }

  //填充IAT表
  pIID = (IMAGE_IMPORT_DESCRIPTOR*)((pOPHead->DataDirectory[1].VirtualAddress)
    + (DWORD)pImageBase);
  while (pIID->Name != 0)
  {
    char *pDllName;
    char *pFacName;
    
    HMODULE hDll;
    IMAGE_THUNK_DATA32 *pIDT,*pIAT;
    PIMAGE_IMPORT_BY_NAME *pImByName;
    pDllName = (char*)((DWORD)(pIID->Name) + (DWORD)pImageBase);
    hDll = LoadLibrary((LPCSTR)pDllName);
    pIDT = (IMAGE_THUNK_DATA32*)(pIID->OriginalFirstThunk + 
      (DWORD)pImageBase);
    pIAT = (IMAGE_THUNK_DATA32*)(pIID->FirstThunk + (DWORD)pImageBase);
    
    while (*(DWORD*)pIDT != 0)
    {
      pImByName = (PIMAGE_IMPORT_BY_NAME*)((DWORD)(pIDT->u1.AddressOfData)
        + (DWORD)pImageBase);
      pFacName =(char*)pImByName+2;
      pIAT->u1.Function = (PDWORD)GetProcAddress(hDll,pFacName);
      pIDT++ ;
    }
    pIID++;
  }
//调用DLLMAIN
  _asm
  {
    pushad;
    push 0;
    push DLL_PROCESS_ATTACH;
    push pImageBase;
    call OEP;
    add esp,0x4;     //DLLMAIN未平衡堆栈。
    popad
  }
  
  return (HMODULE)pImageBase;
  

}

用此函数加载的DLL。有部分API会发生问题。比如:GetProcAddress,GetModulHandle。另外,本函数也没有考虑TLS的处理。等以后有时间在慢慢修补吧。