Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

633 lines
15 KiB

  1. #include "pefile.h"
  2. HANDLE hDll;
  3. /*
  4. BOOL WINAPI DLLEntry (
  5. HANDLE hModule,
  6. DWORD dwFunction,
  7. LPVOID lpNot)
  8. {
  9. hDll = hModule;
  10. return TRUE;
  11. }
  12. */
  13. /* copy dos header information to structure */
  14. BOOL WINAPI GetDosHeader (
  15. LPVOID lpFile,
  16. PIMAGE_DOS_HEADER pHeader)
  17. {
  18. /* dos header rpresents first structure of bytes in file */
  19. if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
  20. CopyMemory ((LPVOID)pHeader, lpFile, sizeof (IMAGE_DOS_HEADER));
  21. else
  22. return FALSE;
  23. return TRUE;
  24. }
  25. /* return file signature */
  26. DWORD WINAPI ImageFileType (
  27. LPVOID lpFile)
  28. {
  29. /* dos file signature comes first */
  30. if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
  31. {
  32. /* determine location of PE File header from dos header */
  33. if (LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE ||
  34. LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE)
  35. return (DWORD)LOWORD(*(DWORD *)NTSIGNATURE (lpFile));
  36. else if (*(DWORD *)NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE)
  37. return IMAGE_NT_SIGNATURE;
  38. else
  39. return IMAGE_DOS_SIGNATURE;
  40. }
  41. else
  42. /* unknown file type */
  43. return 0;
  44. }
  45. /* copy file header information to structure */
  46. BOOL WINAPI GetPEFileHeader (
  47. LPVOID lpFile,
  48. PIMAGE_FILE_HEADER pHeader)
  49. {
  50. /* file header follows dos header */
  51. if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
  52. CopyMemory ((LPVOID)pHeader, PEFHDROFFSET (lpFile), sizeof (IMAGE_FILE_HEADER));
  53. else
  54. return FALSE;
  55. return TRUE;
  56. }
  57. /* copy optional header info to structure */
  58. BOOL WINAPI GetPEOptionalHeader (
  59. LPVOID lpFile,
  60. PIMAGE_OPTIONAL_HEADER pHeader)
  61. {
  62. /* optional header follows file header and dos header */
  63. if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
  64. CopyMemory ((LPVOID)pHeader, OPTHDROFFSET (lpFile), sizeof (IMAGE_OPTIONAL_HEADER));
  65. else
  66. return FALSE;
  67. return TRUE;
  68. }
  69. /* function returns the entry point for an exe module lpFile must
  70. be a memory mapped file pointer to the beginning of the image file */
  71. LONG_PTR WINAPI GetModuleEntryPoint (
  72. LPVOID lpFile)
  73. {
  74. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  75. if (poh != NULL)
  76. return (LONG_PTR)(poh->AddressOfEntryPoint);
  77. else
  78. return 0L;
  79. }
  80. /* return the total number of sections in the module */
  81. int WINAPI NumOfSections (
  82. LPVOID lpFile)
  83. {
  84. /* number os sections is indicated in file header */
  85. return ((int)((PIMAGE_FILE_HEADER)PEFHDROFFSET (lpFile))->NumberOfSections);
  86. }
  87. /* retrieve entry point */
  88. LPVOID WINAPI GetImageBase (
  89. LPVOID lpFile)
  90. {
  91. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  92. if (poh != NULL)
  93. return (LPVOID)(poh->ImageBase);
  94. else
  95. return NULL;
  96. }
  97. /* return offset to specified IMAGE_DIRECTORY entry */
  98. LPVOID WINAPI ImageDirectoryOffset (
  99. LPVOID lpFile,
  100. DWORD dwIMAGE_DIRECTORY)
  101. {
  102. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  103. PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile);
  104. int nSections = NumOfSections (lpFile);
  105. int i = 0;
  106. LONG_PTR VAImageDir;
  107. /* must be 0 thru (NumberOfRvaAndSizes-1) */
  108. if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
  109. return NULL;
  110. /* locate specific image directory's relative virtual address */
  111. VAImageDir = (LONG_PTR)poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
  112. /* locate section containing image directory */
  113. while (i++<nSections)
  114. {
  115. if (psh->VirtualAddress <= (DWORD)VAImageDir &&
  116. psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir)
  117. break;
  118. psh++;
  119. }
  120. if (i > nSections)
  121. return NULL;
  122. /* return image import directory offset */
  123. return (LPVOID)(((LONG_PTR)lpFile + (LONG_PTR)VAImageDir - psh->VirtualAddress) +
  124. (LONG_PTR)psh->PointerToRawData);
  125. }
  126. /* function retrieve names of all the sections in the file */
  127. int WINAPI GetSectionNames (
  128. LPVOID lpFile,
  129. HANDLE hHeap,
  130. char **pszSections)
  131. {
  132. int nSections = NumOfSections (lpFile);
  133. int i, nCnt = 0;
  134. PIMAGE_SECTION_HEADER psh;
  135. char *ps;
  136. if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE ||
  137. (psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) == NULL)
  138. return 0;
  139. /* count the number of chars used in the section names */
  140. for (i=0; i<nSections; i++)
  141. nCnt += strlen (psh[i].Name) + 1;
  142. /* allocate space for all section names from heap */
  143. ps = *pszSections = (char *)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
  144. for (i=0; i<nSections; i++)
  145. {
  146. strcpy (ps, psh[i].Name);
  147. ps += strlen (psh[i].Name) + 1;
  148. }
  149. return nCnt;
  150. }
  151. /* function gets the function header for a section identified by name */
  152. BOOL WINAPI GetSectionHdrByName (
  153. LPVOID lpFile,
  154. IMAGE_SECTION_HEADER *sh,
  155. char *szSection)
  156. {
  157. PIMAGE_SECTION_HEADER psh;
  158. int nSections = NumOfSections (lpFile);
  159. int i;
  160. if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
  161. {
  162. /* find the section by name */
  163. for (i=0; i<nSections; i++)
  164. {
  165. if (!strcmp (psh->Name, szSection))
  166. {
  167. /* copy data to header */
  168. CopyMemory ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
  169. return TRUE;
  170. }
  171. else
  172. psh++;
  173. }
  174. }
  175. return FALSE;
  176. }
  177. /* get import modules names separated by null terminators, return module count */
  178. int WINAPI GetImportModuleNames (
  179. LPVOID lpFile,
  180. // HANDLE hHeap,
  181. char* SectionName,
  182. char **pszModules)
  183. {
  184. PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  185. ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  186. IMAGE_SECTION_HEADER idsh;
  187. BYTE *pData = (BYTE *)pid;
  188. int nCnt = 0, nSize = 0, i;
  189. char *pModule[1024]; /* hardcoded maximum number of modules?? */
  190. char *psz;
  191. /* locate section header for ".idata" section */
  192. if (!GetSectionHdrByName (lpFile, &idsh, SectionName /*".idata" "INIT"*/))
  193. return 0;
  194. /* extract all import modules */
  195. while (pid->dwRVAModuleName)
  196. {
  197. /* allocate temporary buffer for absolute string offsets */
  198. pModule[nCnt] = (char *)(pData + (pid->dwRVAModuleName-idsh.VirtualAddress));
  199. nSize += strlen (pModule[nCnt]) + 1;
  200. /* increment to the next import directory entry */
  201. pid++;
  202. nCnt++;
  203. }
  204. /* copy all strings to one chunk of heap memory */
  205. *pszModules = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
  206. psz = *pszModules;
  207. for (i=0; i<nCnt; i++)
  208. {
  209. strcpy (psz, pModule[i]);
  210. psz += strlen (psz) + 1;
  211. }
  212. return nCnt;
  213. }
  214. /* get import module function names separated by null terminators, return function count */
  215. int WINAPI GetImportFunctionNamesByModule (
  216. LPVOID lpFile,
  217. // HANDLE hHeap,
  218. char* SectionName,
  219. char *pszModule,
  220. char **pszFunctions)
  221. {
  222. PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  223. ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  224. IMAGE_SECTION_HEADER idsh;
  225. LONG_PTR dwBase;
  226. int nCnt = 0, nSize = 0;
  227. DWORD dwFunction;
  228. char *psz;
  229. /* locate section header for ".idata" section */
  230. if (!GetSectionHdrByName (lpFile, &idsh, SectionName/*".idata" "INIT"*/))
  231. return 0;
  232. dwBase = ((LONG_PTR)pid - idsh.VirtualAddress);
  233. /* find module's pid */
  234. while (pid->dwRVAModuleName &&
  235. strcmp (pszModule, (char *)(pid->dwRVAModuleName+dwBase)))
  236. pid++;
  237. /* exit if the module is not found */
  238. if (!pid->dwRVAModuleName)
  239. return 0;
  240. /* count number of function names and length of strings */
  241. dwFunction = pid->dwRVAFunctionNameList;
  242. while (dwFunction &&
  243. *(DWORD *)(dwFunction + dwBase) &&
  244. *(char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2))
  245. {
  246. nSize += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  247. dwFunction += 4;
  248. nCnt++;
  249. }
  250. /* allocate memory off heap for function names */
  251. *pszFunctions = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
  252. psz = *pszFunctions;
  253. /* copy function names to mempry pointer */
  254. dwFunction = pid->dwRVAFunctionNameList;
  255. while (dwFunction &&
  256. *(DWORD *)(dwFunction + dwBase) &&
  257. *((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)))
  258. {
  259. strcpy (psz, (char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2));
  260. psz += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  261. dwFunction += 4;
  262. }
  263. return nCnt;
  264. }
  265. /* get exported function names separated by null terminators, return count of functions */
  266. int WINAPI GetExportFunctionNames (
  267. LPVOID lpFile,
  268. HANDLE hHeap,
  269. char **pszFunctions)
  270. {
  271. IMAGE_SECTION_HEADER sh;
  272. PIMAGE_EXPORT_DIRECTORY ped;
  273. char *pNames, *pCnt;
  274. int i, nCnt;
  275. /* get section header and pointer to data directory for .edata section */
  276. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  277. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  278. return 0;
  279. GetSectionHdrByName (lpFile, &sh, ".edata");
  280. /* determine the offset of the export function names */
  281. pNames = (char *)(*(int *)((int)ped->AddressOfNames -
  282. (int)sh.VirtualAddress +
  283. (int)sh.PointerToRawData +
  284. (LONG_PTR)lpFile) -
  285. (int)sh.VirtualAddress +
  286. (int)sh.PointerToRawData +
  287. (LONG_PTR)lpFile);
  288. /* figure out how much memory to allocate for all strings */
  289. pCnt = pNames;
  290. for (i=0; i<(int)ped->NumberOfNames; i++)
  291. while (*pCnt++);
  292. nCnt = (int)(pCnt - pNames);
  293. /* allocate memory off heap for function names */
  294. *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
  295. /* copy all string to buffer */
  296. CopyMemory ((LPVOID)*pszFunctions, (LPVOID)pNames, nCnt);
  297. return nCnt;
  298. }
  299. /* return the number of exported functions in the module */
  300. int WINAPI GetNumberOfExportedFunctions (
  301. LPVOID lpFile)
  302. {
  303. PIMAGE_EXPORT_DIRECTORY ped;
  304. /* get section header and pointer to data directory for .edata section */
  305. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  306. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  307. return 0;
  308. else
  309. return (int)ped->NumberOfNames;
  310. }
  311. /* return a pointer to the list of function entry points */
  312. LPVOID WINAPI GetExportFunctionEntryPoints (
  313. LPVOID lpFile)
  314. {
  315. IMAGE_SECTION_HEADER sh;
  316. PIMAGE_EXPORT_DIRECTORY ped;
  317. /* get section header and pointer to data directory for .edata section */
  318. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  319. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  320. return NULL;
  321. GetSectionHdrByName (lpFile, &sh, ".edata");
  322. /* determine the offset of the export function entry points */
  323. return (LPVOID) ((int)ped->AddressOfFunctions -
  324. (int)sh.VirtualAddress +
  325. (int)sh.PointerToRawData +
  326. (LONG_PTR)lpFile);
  327. }
  328. /* return a pointer to the list of function ordinals */
  329. LPVOID WINAPI GetExportFunctionOrdinals (
  330. LPVOID lpFile)
  331. {
  332. IMAGE_SECTION_HEADER sh;
  333. PIMAGE_EXPORT_DIRECTORY ped;
  334. /* get section header and pointer to data directory for .edata section */
  335. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  336. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  337. return NULL;
  338. GetSectionHdrByName (lpFile, &sh, ".edata");
  339. /* determine the offset of the export function entry points */
  340. return (LPVOID) ((int)ped->AddressOfNameOrdinals -
  341. (int)sh.VirtualAddress +
  342. (int)sh.PointerToRawData +
  343. (LONG_PTR)lpFile);
  344. }
  345. /* determine the total number of resources in the section */
  346. int WINAPI GetNumberOfResources (
  347. LPVOID lpFile)
  348. {
  349. PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
  350. PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
  351. int nCnt=0, i;
  352. /* get root directory of resource tree */
  353. if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
  354. (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
  355. return 0;
  356. /* set pointer to first resource type entry */
  357. prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LONG_PTR)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
  358. /* loop through all resource directory entry types */
  359. for (i=0; i<prdRoot->NumberOfIdEntries; i++)
  360. {
  361. /* locate directory or each resource type */
  362. prdType = (PIMAGE_RESOURCE_DIRECTORY)((LONG_PTR)prdRoot + (LONG_PTR)prde->OffsetToData);
  363. /* mask off most significant bit of the data offset */
  364. prdType = (PIMAGE_RESOURCE_DIRECTORY)((LONG_PTR)prdType ^ 0x80000000);
  365. /* increment count of name'd and ID'd resources in directory */
  366. nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
  367. /* increment to next entry */
  368. prde++;
  369. }
  370. return nCnt;
  371. }
  372. /* name each type of resource in the section */
  373. int WINAPI GetListOfResourceTypes (
  374. LPVOID lpFile,
  375. HANDLE hHeap,
  376. char **pszResTypes)
  377. {
  378. PIMAGE_RESOURCE_DIRECTORY prdRoot;
  379. PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
  380. char *pMem;
  381. int nCnt, i;
  382. /* get root directory of resource tree */
  383. if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
  384. (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
  385. return 0;
  386. /* allocate enuff space from heap to cover all types */
  387. nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1);
  388. *pszResTypes = (char *)HeapAlloc (hHeap,
  389. HEAP_ZERO_MEMORY,
  390. nCnt);
  391. if ((pMem = *pszResTypes) == NULL)
  392. return 0;
  393. /* set pointer to first resource type entry */
  394. prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LONG_PTR)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
  395. /* loop through all resource directory entry types */
  396. for (i=0; i<prdRoot->NumberOfIdEntries; i++)
  397. {
  398. if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME))
  399. pMem += strlen (pMem) + 1;
  400. prde++;
  401. }
  402. return nCnt;
  403. }
  404. /* function indicates whether debug info has been stripped from file */
  405. BOOL WINAPI IsDebugInfoStripped (
  406. LPVOID lpFile)
  407. {
  408. PIMAGE_FILE_HEADER pfh;
  409. pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET (lpFile);
  410. return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
  411. }
  412. /* retrieve the module name from the debug misc. structure */
  413. int WINAPI RetrieveModuleName (
  414. LPVOID lpFile,
  415. HANDLE hHeap,
  416. char **pszModule)
  417. {
  418. PIMAGE_DEBUG_DIRECTORY pdd;
  419. PIMAGE_DEBUG_MISC pdm = NULL;
  420. int nCnt;
  421. if (!(pdd = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG)))
  422. return 0;
  423. while (pdd->SizeOfData)
  424. {
  425. if (pdd->Type == IMAGE_DEBUG_TYPE_MISC)
  426. {
  427. pdm = (PIMAGE_DEBUG_MISC)((DWORD)pdd->PointerToRawData + (LONG_PTR)lpFile);
  428. *pszModule = (char *)HeapAlloc (hHeap,
  429. HEAP_ZERO_MEMORY,
  430. (nCnt = (lstrlen (pdm->Data)*(pdm->Unicode?2:1)))+1);
  431. CopyMemory (*pszModule, pdm->Data, nCnt);
  432. break;
  433. }
  434. pdd ++;
  435. }
  436. if (pdm != NULL)
  437. return nCnt;
  438. else
  439. return 0;
  440. }
  441. /* determine if this is a valid debug file */
  442. BOOL WINAPI IsDebugFile (
  443. LPVOID lpFile)
  444. {
  445. PIMAGE_SEPARATE_DEBUG_HEADER psdh;
  446. psdh = (PIMAGE_SEPARATE_DEBUG_HEADER)lpFile;
  447. return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE);
  448. }
  449. /* copy separate debug header structure from debug file */
  450. BOOL WINAPI GetSeparateDebugHeader (
  451. LPVOID lpFile,
  452. PIMAGE_SEPARATE_DEBUG_HEADER psdh)
  453. {
  454. PIMAGE_SEPARATE_DEBUG_HEADER pdh;
  455. pdh = (PIMAGE_SEPARATE_DEBUG_HEADER)lpFile;
  456. if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
  457. {
  458. CopyMemory ((LPVOID)psdh, (LPVOID)pdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER));
  459. return TRUE;
  460. }
  461. return FALSE;
  462. }