home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / walker / pefile.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  14KB  |  482 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. #include "pefile.h"
  13.  
  14.  
  15.  
  16. PIMAGE_SECTION_HEADER    WINAPI IDSectionHeaderOffset (LPVOID);
  17.  
  18.  
  19. BOOL WINAPI DllMain (
  20.     HANDLE    hModule,
  21.     DWORD     dwFunction,
  22.     LPVOID    lpNot)
  23. {
  24.     return TRUE;
  25. }
  26.  
  27.  
  28.  
  29. /* return offset to file header */
  30. PIMAGE_FILE_HEADER   WINAPI FileHeaderOffset (
  31.     LPVOID    lpFile)
  32. {
  33.     int              ImageHdrOffset = 0;
  34.  
  35.     /* if DOS based file, skip DOS header and file signature */
  36.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  37.     {
  38.     /* file image header offset exists after DOS header and nt signature */
  39.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  40.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) != IMAGE_NT_SIGNATURE)
  41.         return NULL;
  42.     }
  43.  
  44.     /* optional header exists immediately after file header and image header */
  45.     return (PIMAGE_FILE_HEADER)((int)lpFile + ImageHdrOffset);
  46. }
  47.  
  48.  
  49.  
  50.  
  51. /* return optional header data */
  52. PIMAGE_OPTIONAL_HEADER    WINAPI OptionalHeaderOffset (
  53.     LPVOID    lpFile)
  54. {
  55.     int              ImageHdrOffset = 0;
  56.  
  57.     /* if DOS based file, skip DOS header and file signature */
  58.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  59.     {
  60.     /* file image header offset exists after DOS header and nt signature */
  61.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  62.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) != IMAGE_NT_SIGNATURE)
  63.         return NULL;
  64.     }
  65.  
  66.     /* optional header exists immediately after file header and image header */
  67.     return (PIMAGE_OPTIONAL_HEADER)((char *)lpFile + ImageHdrOffset + sizeof (IMAGE_FILE_HEADER));
  68. }
  69.  
  70.  
  71.  
  72.  
  73. /* return pointer to first section header */
  74. PIMAGE_SECTION_HEADER    WINAPI SectionHeaderOffset (
  75.     LPVOID    lpFile)
  76. {
  77.     int              ImageHdrOffset = 0;
  78.  
  79.     /* if DOS based file, skip DOS header and file signature */
  80.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  81.     {
  82.     /* file image header offset exists after DOS header and nt signature */
  83.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  84.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) != IMAGE_NT_SIGNATURE)
  85.         return NULL;
  86.     }
  87.  
  88.     /* optional header exists immediately after file header and image header */
  89.     return (PIMAGE_SECTION_HEADER)((int)OptionalHeaderOffset (lpFile) +
  90.     (int)((PIMAGE_FILE_HEADER)((int)lpFile + ImageHdrOffset))->SizeOfOptionalHeader);
  91. }
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /* return offset to first IMAGE_IMPORT_DIRECTORY entry */
  98. PIMAGE_IMPORT_DIRECTORY  WINAPI ImportDirectoryOffset (
  99.     LPVOID      lpFile)
  100. {
  101.     PIMAGE_OPTIONAL_HEADER   poh = OptionalHeaderOffset (lpFile);
  102.     PIMAGE_SECTION_HEADER    psh = SectionHeaderOffset (lpFile);
  103.     int              nSections = NumOfSections (lpFile);
  104.     int              i = 0;
  105.     LPVOID             VAImportDir;
  106.  
  107.     VAImportDir = (LPVOID)poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  108.  
  109.     /* locate section containing import directory */
  110.     while (i++<nSections)
  111.     {
  112.     if (psh->VirtualAddress <= (DWORD)VAImportDir &&
  113.         psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImportDir)
  114.         break;
  115.     psh++;
  116.     }
  117.  
  118.     if (i > nSections)
  119.     return 0;
  120.  
  121.     /* return image import directory offset */
  122.     return (PIMAGE_IMPORT_DIRECTORY)(((int)lpFile + (int)VAImportDir - psh->VirtualAddress) +
  123.                    (int)psh->PointerToRawData);
  124. }
  125.  
  126.  
  127.  
  128.  
  129. /* return pointer to image directory section header */
  130. PIMAGE_SECTION_HEADER    WINAPI IDSectionHeaderOffset (
  131.     LPVOID    lpFile)
  132. {
  133.     int              ImageHdrOffset = 0;
  134.     PIMAGE_OPTIONAL_HEADER   poh = OptionalHeaderOffset (lpFile);
  135.     PIMAGE_SECTION_HEADER    psh = SectionHeaderOffset (lpFile);
  136.     int              nSections = NumOfSections (lpFile);
  137.     int              i = 0;
  138.     LPVOID             VAImportDir;
  139.  
  140.     VAImportDir = (LPVOID)poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  141.  
  142.     /* locate section containing import directory */
  143.     while (i++<nSections)
  144.     {
  145.     if (psh->VirtualAddress <= (DWORD)VAImportDir &&
  146.         psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImportDir)
  147.         break;
  148.     psh++;
  149.     }
  150.  
  151.     if (i > nSections)
  152.     return 0;
  153.     else
  154.     return psh;
  155. }
  156.  
  157.  
  158.  
  159.  
  160.  
  161. /* return the total number of sections in the module */
  162. int   WINAPI NumOfSections (
  163.     LPVOID    lpFile)
  164. {
  165.     int              ImageHdrOffset = 0;
  166.  
  167.     /* if DOS based file, skip DOS header and file signature */
  168.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  169.     {
  170.     /* file image header offset exists after DOS header and nt signature */
  171.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  172.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) != IMAGE_NT_SIGNATURE)
  173.         return 0;
  174.     }
  175.  
  176.     /* section total is found in the file header */
  177.     return (int)((PIMAGE_FILE_HEADER)((int)lpFile + ImageHdrOffset))->NumberOfSections;
  178. }
  179.  
  180.  
  181.  
  182. /* retrieve name of module from module's open file handle */
  183. void WINAPI RetrieveModuleName (
  184.     char      *lpszModule,
  185.     HANDLE    hFile)
  186. {
  187.     HANDLE             hMapFile;
  188.     LPVOID             lpFile;
  189.     char             *lpszName;
  190.     int              nSections;
  191.     ULONG             VAExportDir;
  192.     int              i=0;
  193.     int              ImageHdrOffset;
  194.     PIMAGE_SECTION_HEADER    psh;
  195.     PIMAGE_FILE_HEADER         pfh;
  196.     PIMAGE_OPTIONAL_HEADER   poh;
  197.     PIMAGE_EXPORT_DIRECTORY  ped;
  198.  
  199.  
  200.     /* memory map handle to DLL for easy access */
  201.     hMapFile = CreateFileMapping (hFile,
  202.                   (LPSECURITY_ATTRIBUTES)NULL,
  203.                   PAGE_READONLY,
  204.                   0,
  205.                   0,
  206.                   NULL);
  207.  
  208.     /* map view of entire file */
  209.     lpFile = MapViewOfFile (hMapFile, FILE_MAP_READ, 0, 0, 0);
  210.  
  211.     /* if DOS based file */
  212.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  213.     {
  214.     /* file image header offset exists after DOS header and nt signature */
  215.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  216.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) !=
  217.         IMAGE_NT_SIGNATURE)
  218.         {
  219.         strcpy (lpszModule, "Error, no IMAGE_NT_SIGNATURE");
  220.         goto EXIT;
  221.         }
  222.     }
  223.  
  224.     pfh = (PIMAGE_FILE_HEADER)((char *)lpFile + ImageHdrOffset);
  225.  
  226.     /* if optional header exists and exports directory exists proceed */
  227.     if (pfh->SizeOfOptionalHeader)
  228.     {
  229.     /* locate virtual address for Export Image Directory in OptionalHeader */
  230.     poh = (PIMAGE_OPTIONAL_HEADER)((char *)pfh + sizeof (IMAGE_FILE_HEADER));
  231.     VAExportDir = poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  232.  
  233.     /* locate section where export virtual address is located */
  234.     psh = (PIMAGE_SECTION_HEADER)((char *)poh + pfh->SizeOfOptionalHeader);
  235.     nSections = pfh->NumberOfSections;
  236.     while (i++<nSections)
  237.         {
  238.         if (psh->VirtualAddress <= VAExportDir &&
  239.         psh->VirtualAddress + psh->SizeOfRawData > VAExportDir)
  240.         break;
  241.         psh++;
  242.         }
  243.  
  244.     /* locate export image directory */
  245.     if (i < nSections)
  246.         ped = (PIMAGE_EXPORT_DIRECTORY)((char *)lpFile +
  247.         (VAExportDir - psh->VirtualAddress) + psh->PointerToRawData);
  248.     else
  249.         {
  250.         strcpy (lpszModule, "IMAGE_EXPORT_DIRECTORY not found");
  251.         goto EXIT;
  252.         }
  253.  
  254.     /* read name from export directory */
  255.     lpszName = (char *)lpFile + ped->Name + (psh->PointerToRawData - psh->VirtualAddress);
  256.     strcpy (lpszModule, lpszName);
  257.     }
  258.  
  259.     else
  260.     strcpy (lpszModule, "Error, no IMAGE_OPTIONAL_HEADER");
  261.  
  262. EXIT:
  263.     /* clean up before exiting */
  264.     UnmapViewOfFile (lpFile);
  265.     CloseHandle (hMapFile);
  266. }
  267.  
  268.  
  269.  
  270.  
  271. /* retieve section names from module file handle */
  272. void WINAPI RetrieveSectionNames (
  273.     HANDLE      hHeap,
  274.     HANDLE      hFile,
  275.     SECTIONINFO   **pSection)
  276. {
  277.     HANDLE             hMapFile;
  278.     LPVOID             lpFile;
  279.     int              nSections;
  280.     int              i=0;
  281.     int              ImageHdrOffset;
  282.     PIMAGE_SECTION_HEADER    psh;
  283.     PIMAGE_FILE_HEADER         pfh;
  284.     SECTIONINFO          *ps;
  285.  
  286.  
  287.     /* memory map handle to DLL for easy access */
  288.     hMapFile = CreateFileMapping (hFile,
  289.                   (LPSECURITY_ATTRIBUTES)NULL,
  290.                   PAGE_READONLY,
  291.                   0,
  292.                   0,
  293.                   NULL);
  294.  
  295.     /* map view of entire file */
  296.     lpFile = MapViewOfFile (hMapFile, FILE_MAP_READ, 0, 0, 0);
  297.  
  298.     /* if DOS based file */
  299.     if (*((USHORT *)lpFile) == IMAGE_DOS_SIGNATURE)
  300.     {
  301.     /* file image header offset exists after DOS header and nt signature */
  302.     ImageHdrOffset = (int)((ULONG *)lpFile)[15] + sizeof (ULONG);
  303.     if (*((ULONG *)((char *)lpFile + ImageHdrOffset - sizeof (ULONG))) !=
  304.         IMAGE_NT_SIGNATURE)
  305.         goto EXIT;
  306.     }
  307.  
  308.     pfh = (PIMAGE_FILE_HEADER)((char *)lpFile + ImageHdrOffset);
  309.  
  310.     /* if optional header exists, offset first section header */
  311.     psh = (PIMAGE_SECTION_HEADER)((char *)pfh +
  312.           sizeof (IMAGE_FILE_HEADER) + pfh->SizeOfOptionalHeader);
  313.  
  314.     /* allocate one section header for each section */
  315.     ps = *pSection = (SECTIONINFO *)HeapAlloc (hHeap,
  316.                            HEAP_ZERO_MEMORY,
  317.                            sizeof (SECTIONINFO));
  318.     nSections = pfh->NumberOfSections;
  319.     while (TRUE)
  320.     {
  321.     strcpy (ps->szSection, psh[i].Name);
  322.     ps->uVirtualAddress = psh[i].VirtualAddress;
  323.     ps->uSize = psh[i].SizeOfRawData;
  324.  
  325.     if (++i >= nSections)
  326.         break;
  327.  
  328.     /* allocate heap memory for sections */
  329.     ps->Next = (LPSECTIONINFO)HeapAlloc (hHeap,
  330.                          HEAP_ZERO_MEMORY,
  331.                          sizeof (SECTIONINFO));
  332.     ps = (SECTIONINFO *)ps->Next;
  333.     }
  334.  
  335. EXIT:
  336.     /* clean up before exiting */
  337.     UnmapViewOfFile (lpFile);
  338.     CloseHandle (hMapFile);
  339. }
  340.  
  341.  
  342.  
  343.  
  344. /* function returns the entry point for an exe module lpFile must
  345.    be a memory mapped file pointer to the beginning of the image file */
  346. LPVOID    WINAPI GetModuleEntryPoint (
  347.     LPVOID    lpFile)
  348. {
  349.     PIMAGE_OPTIONAL_HEADER   poh = OptionalHeaderOffset (lpFile);
  350.  
  351.     if (poh != NULL)
  352.     return (LPVOID)(poh->AddressOfEntryPoint);
  353.     else
  354.     return NULL;
  355. }
  356.  
  357.  
  358.  
  359.  
  360. /* retrieve entry point */
  361. LPVOID    WINAPI GetImageBase (
  362.     LPVOID    lpFile)
  363. {
  364.     PIMAGE_OPTIONAL_HEADER   poh = OptionalHeaderOffset (lpFile);
  365.  
  366.     if (poh != NULL)
  367.     return (LPVOID)(poh->ImageBase);
  368.     else
  369.     return NULL;
  370. }
  371.  
  372.  
  373.  
  374.  
  375. /* get import modules names separated by null terminators, return module count */
  376. int  WINAPI GetImportModuleNames (
  377.     LPVOID    lpFile,
  378.     HANDLE    hHeap,
  379.     char      **pszModules)
  380. {
  381.     PIMAGE_IMPORT_DIRECTORY  pid = ImportDirectoryOffset (lpFile);
  382.     PIMAGE_SECTION_HEADER    pidsh = IDSectionHeaderOffset (lpFile);
  383.     BYTE             *pData = (BYTE *)pid;
  384.     int              nCnt = 0, nSize = 0, i;
  385.     char             *pModule[1024];  /* hardcoded maximum number of modules?? */
  386.     char             *psz;
  387.  
  388.     /* extract all import modules */
  389.     while (pid->dwRVAModule)
  390.     {
  391.     /* allocate temporary buffer for absolute string offsets */
  392.     pModule[nCnt] = (char *)(pData + (pid->dwRVAModule-pidsh->VirtualAddress));
  393.     nSize += strlen (pModule[nCnt]) + 1;
  394.  
  395.     /* increment to the next import directory entry */
  396.     pid++;
  397.     nCnt++;
  398.     }
  399.  
  400.     /* copy all strings to one chunk of heap memory */
  401.     *pszModules = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nSize);
  402.     psz = *pszModules;
  403.     for (i=0; i<nCnt; i++)
  404.     {
  405.     strcpy (psz, pModule[i]);
  406.     psz += strlen (psz) + 1;
  407.     }
  408.  
  409.     return nCnt;
  410. }
  411.  
  412.  
  413.  
  414.  
  415. /* get import module function names separated by null terminators, return function count */
  416. int  WINAPI GetImportFunctionNamesByModule (
  417.     LPVOID    lpFile,
  418.     HANDLE    hHeap,
  419.     char      *pszModule,
  420.     char      **pszFunctions)
  421. {
  422.     PIMAGE_IMPORT_DIRECTORY  pid = ImportDirectoryOffset (lpFile);
  423.     PIMAGE_SECTION_HEADER    pidsh = IDSectionHeaderOffset (lpFile);
  424.     DWORD             dwBase = ((DWORD)pid - pidsh->VirtualAddress);
  425.     int              nCnt = 0, nSize = 0;
  426.     DWORD             dwFunction;
  427.     char             *psz;
  428.  
  429.     /* find module's pid */
  430.     while (pid->dwRVAModule &&
  431.        strcmp (pszModule, (char *)(pid->dwRVAModule+dwBase)))
  432.     pid++;
  433.  
  434.     /* count functions and total space required for them */
  435.     nSize += strlen ((char *)((*(DWORD *)(pid->dwRVAFirstFunction + dwBase)) + dwBase+2)) + 1;
  436.  
  437.     /* last image directory does not have a separate function list, so improvise */
  438.     if (!(dwFunction = pid->dwRVAFunctionList))
  439.     dwFunction = pid->dwRVAFirstFunction + 4;
  440.  
  441.     while (dwFunction &&
  442.        *(char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2))
  443.     {
  444.     nSize += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  445.     dwFunction += 4;
  446.     nCnt++;
  447.     }
  448.  
  449.     /* allocate memory off heap for function names */
  450.     *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nSize);
  451.     psz = *pszFunctions;
  452.     strcpy (psz, (char *)((*(DWORD *)(pid->dwRVAFirstFunction + dwBase)) + dwBase+2));
  453.     psz += strlen ((char *)((*(DWORD *)(pid->dwRVAFirstFunction + dwBase)) + dwBase+2)) + 1;
  454.  
  455.     /* last image directory does not have a separate function list, so improvise */
  456.     if (!(dwFunction = pid->dwRVAFunctionList))
  457.     dwFunction = pid->dwRVAFirstFunction + 4;
  458.  
  459.     while (dwFunction &&
  460.        *((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)))
  461.     {
  462.     strcpy (psz, (char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2));
  463.     psz += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  464.     dwFunction += 4;
  465.     }
  466.  
  467.     return nCnt;
  468. }
  469.  
  470.  
  471.  
  472.  
  473. /* get exported function names separated by null terminators, return count of functions */
  474. int  WINAPI GetExportFunctionNames (
  475.     LPVOID    lpFile,
  476.     HANDLE    hHeap,
  477.     char      **pszFunctions)
  478. {
  479.  
  480.     return 0;
  481. }
  482.