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.

2263 lines
58 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. modimage.c
  5. Abstract:
  6. Implements a set of routines for examining EXE modules
  7. Author:
  8. Calin Negreanu (calinn) 27-Nov-1997
  9. Revision History:
  10. calinn 08-Mar-2000 Moved over from Win9xUpg project.
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. //
  17. // Debug constants
  18. //
  19. #define DBG_MODIMAGE "ModImage"
  20. //
  21. // Strings
  22. //
  23. // None
  24. //
  25. // Constants
  26. //
  27. #define SEG_CODE_MASK 0x0001
  28. #define SEG_CODE 0x0000
  29. #define SEG_PRELOAD_MASK 0x0040
  30. #define SEG_PRELOAD 0x0040
  31. #define SEG_RELOC_MASK 0x0100
  32. #define SEG_RELOC 0x0100
  33. #define RELOC_IMPORTED_ORDINAL 0x01
  34. #define RELOC_IMPORTED_NAME 0x02
  35. #define RELOC_ADDR_TYPE 0x03
  36. #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
  37. #define IMAGE_NE_SIGNATURE 0x454E // NE
  38. #define IMAGE_PE_SIGNATURE 0x00004550l // PE00
  39. //
  40. // Macros
  41. //
  42. // None
  43. //
  44. // Types
  45. //
  46. #pragma pack(push,1)
  47. typedef struct _DOS_HEADER { // DOS .EXE header
  48. WORD e_magic; // Magic number
  49. WORD e_cblp; // Bytes on last page of file
  50. WORD e_cp; // Pages in file
  51. WORD e_crlc; // Relocations
  52. WORD e_cparhdr; // Size of header in paragraphs
  53. WORD e_minalloc; // Minimum extra paragraphs needed
  54. WORD e_maxalloc; // Maximum extra paragraphs needed
  55. WORD e_ss; // Initial (relative) SS value
  56. WORD e_sp; // Initial SP value
  57. WORD e_csum; // Checksum
  58. WORD e_ip; // Initial IP value
  59. WORD e_cs; // Initial (relative) CS value
  60. WORD e_lfarlc; // File address of relocation table
  61. WORD e_ovno; // Overlay number
  62. WORD e_res[4]; // Reserved words
  63. WORD e_oemid; // OEM identifier (for e_oeminfo)
  64. WORD e_oeminfo; // OEM information; e_oemid specific
  65. WORD e_res2[10]; // Reserved words
  66. LONG e_lfanew; // File address of new exe header
  67. } DOS_HEADER, *PDOS_HEADER;
  68. typedef struct _NE_HEADER {
  69. WORD Magic;
  70. BYTE MajorLinkerVersion;
  71. BYTE MinorLinkerVersion;
  72. WORD EntryTableOff;
  73. WORD EntryTableLen;
  74. ULONG Reserved;
  75. WORD Flags;
  76. WORD NumberOfDataSeg;
  77. WORD SizeOfHeap;
  78. WORD SizeOfStack;
  79. ULONG CS_IP;
  80. ULONG SS_SP;
  81. WORD NumEntriesSegTable;
  82. WORD NumEntriesModuleTable;
  83. WORD NonResNameTableSize;
  84. WORD SegTableOffset;
  85. WORD ResTableOffset;
  86. WORD ResNameTableOffset;
  87. WORD ModuleTableOffset;
  88. WORD ImportedTableOffset;
  89. ULONG NonResNameTableOffset;
  90. WORD NumberOfMovableEntryPoints;
  91. WORD ShiftCount;
  92. WORD NumberOfResourceSegments;
  93. BYTE TargetOS;
  94. BYTE AdditionalInfo;
  95. WORD FastLoadOffset;
  96. WORD FastLoadSize;
  97. WORD Reserved1;
  98. WORD WinVersionExpected;
  99. } NE_HEADER, *PNE_HEADER;
  100. typedef struct {
  101. WORD Signature; // 00h
  102. BYTE LinkerVersion; // 02h
  103. BYTE LinkerRevision; // 03h
  104. WORD OffsetToEntryTable; // 04h
  105. WORD LengthOfEntryTable; // 06h
  106. DWORD Reserved; // 08h
  107. WORD Flags; // 0ch
  108. WORD AutoDataSegment; // 0eh
  109. WORD LocalHeapSize; // 10h
  110. WORD StackSize; // 12h
  111. DWORD EntryAddress; // 14h
  112. DWORD StackAddress; // 18h
  113. WORD SegmentTableEntries; // 1ch
  114. WORD ModuleReferenceTableEntries; // 1eh
  115. WORD NonResidentTableSize; // 20h
  116. WORD OffsetToSegmentTable; // 22h
  117. WORD OffsetToResourceTable; // 24h
  118. WORD OffsetToResidentNameTable; // 26h
  119. WORD OffsetToModuleReferenceTable; // 28h
  120. WORD OffsetToImportedNameTable; // 2ah
  121. WORD OffsetToNonResidentNameTable; // 2ch
  122. WORD Unused; // 2eh
  123. WORD MovableEntryPoints; // 30h
  124. WORD LogicalSectorShiftCount; // 32h
  125. WORD ResourceSegments; // 34h
  126. BYTE TargetOS; // 36h
  127. BYTE AdditionalFlags; // 37h
  128. WORD FastLoadOffset; // 38h
  129. WORD SectorsInFastLoad; // 3ah
  130. WORD Reserved2; // 3ch
  131. WORD WindowsVersion; // 3eh
  132. } NE_INFO_BLOCK, *PNE_INFO_BLOCK;
  133. typedef struct _NE_SEGMENT_ENTRY {
  134. WORD SegmentOffset;
  135. WORD SegmentLen;
  136. WORD SegmentFlags;
  137. WORD SegMinAlloc;
  138. } NE_SEGMENT_ENTRY, *PNE_SEGMENT_ENTRY;
  139. typedef struct _NE_RELOC_ITEM {
  140. BYTE AddressType;
  141. BYTE RelocType;
  142. WORD RelocOffset;
  143. WORD ModuleOffset;
  144. WORD FunctionOffset;
  145. } NE_RELOC_ITEM, *PNE_RELOC_ITEM;
  146. typedef struct {
  147. WORD Offset;
  148. WORD Length;
  149. WORD Flags;
  150. WORD Id;
  151. WORD Handle;
  152. WORD Usage;
  153. } NE_RES_NAMEINFO, *PNE_RES_NAMEINFO;
  154. typedef struct {
  155. WORD TypeId;
  156. WORD ResourceCount;
  157. DWORD Reserved;
  158. NE_RES_NAMEINFO NameInfo[];
  159. } NE_RES_TYPEINFO, *PNE_RES_TYPEINFO;
  160. #pragma pack(pop)
  161. typedef struct {
  162. WORD AlignShift;
  163. GROWLIST TypeInfoArray;
  164. GROWLIST ResourceNames;
  165. } NE_RESOURCES, *PNE_RESOURCES;
  166. typedef struct {
  167. PLOADED_IMAGE Image;
  168. PIMAGE_IMPORT_DESCRIPTOR ImageDescriptor;
  169. DWORD ImportFunctionAddr;
  170. PIMAGE_THUNK_DATA ImageData;
  171. PIMAGE_IMPORT_BY_NAME ImageName;
  172. } MD_IMPORT_ENUM32_HANDLE, *PMD_IMPORT_ENUM32_HANDLE;
  173. typedef struct {
  174. PBYTE Image;
  175. PDOS_HEADER DosHeader;
  176. PNE_HEADER NeHeader;
  177. PNE_SEGMENT_ENTRY SegmentEntry;
  178. WORD CurrSegEntry;
  179. PWORD CurrNrReloc;
  180. PNE_RELOC_ITEM RelocItem;
  181. WORD CurrRelocItem;
  182. } MD_IMPORT_ENUM16_HANDLE, *PMD_IMPORT_ENUM16_HANDLE;
  183. typedef struct {
  184. HANDLE File;
  185. DWORD HeaderOffset;
  186. NE_INFO_BLOCK Header;
  187. NE_RESOURCES Resources;
  188. BOOL ResourcesLoaded;
  189. PMHANDLE ResourcePool;
  190. } NE_HANDLE, *PNE_HANDLE;
  191. typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXA)(HMODULE hModule, PCSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
  192. typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXW)(HMODULE hModule, PCWSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
  193. typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXA)(HMODULE hModule, PCSTR lpType,
  194. PSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
  195. typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXW)(HMODULE hModule, PCWSTR lpType,
  196. PWSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
  197. typedef struct {
  198. PCSTR TypeToFind;
  199. PNE_RES_TYPEINFO OutboundTypeInfo;
  200. BOOL Found;
  201. } TYPESEARCHDATAA, *PTYPESEARCHDATAA;
  202. typedef struct {
  203. PCSTR NameToFind;
  204. PNE_RES_TYPEINFO OutboundTypeInfo;
  205. PNE_RES_NAMEINFO OutboundNameInfo;
  206. BOOL Found;
  207. } NAMESEARCHDATAA, *PNAMESEARCHDATAA;
  208. //
  209. // Globals
  210. //
  211. // None
  212. //
  213. // Macro expansion list
  214. //
  215. // None
  216. //
  217. // Private function prototypes
  218. //
  219. // None
  220. //
  221. // Macro expansion definition
  222. //
  223. // None
  224. //
  225. // Code
  226. //
  227. BOOL
  228. MdLoadModuleDataA (
  229. IN PCSTR ModuleName,
  230. OUT PMD_MODULE_IMAGE ModuleImage
  231. )
  232. {
  233. HANDLE fileHandle;
  234. DWORD bytesRead;
  235. DOS_HEADER dh;
  236. DWORD sign;
  237. PWORD signNE = (PWORD)&sign;
  238. BOOL result = FALSE;
  239. ZeroMemory (ModuleImage, sizeof (MD_MODULE_IMAGE));
  240. fileHandle = CreateFileA (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  241. if (fileHandle == INVALID_HANDLE_VALUE) {
  242. ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
  243. return FALSE;
  244. }
  245. __try {
  246. __try {
  247. if ((!ReadFile (fileHandle, &dh, sizeof (DOS_HEADER), &bytesRead, NULL)) ||
  248. (bytesRead != sizeof (DOS_HEADER))
  249. ) {
  250. __leave;
  251. }
  252. result = TRUE;
  253. if (dh.e_magic != IMAGE_DOS_SIGNATURE) {
  254. ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
  255. __leave;
  256. }
  257. ModuleImage->ModuleType = MODULETYPE_DOS;
  258. if (SetFilePointer (fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) {
  259. __leave;
  260. }
  261. if ((!ReadFile (fileHandle, &sign, sizeof (DWORD), &bytesRead, NULL)) ||
  262. (bytesRead != sizeof (DWORD))
  263. ) {
  264. __leave;
  265. }
  266. CloseHandle (fileHandle);
  267. fileHandle = INVALID_HANDLE_VALUE;
  268. if (sign == IMAGE_PE_SIGNATURE) {
  269. ModuleImage->ModuleType = MODULETYPE_WIN32;
  270. result = MapAndLoad ((PSTR)ModuleName, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE);
  271. }
  272. if (*signNE == IMAGE_NE_SIGNATURE) {
  273. ModuleImage->ModuleType = MODULETYPE_WIN16;
  274. ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemoryA (
  275. ModuleName,
  276. &ModuleImage->ModuleData.W16Data.FileHandle,
  277. &ModuleImage->ModuleData.W16Data.MapHandle
  278. );
  279. result = (ModuleImage->ModuleData.W16Data.Image != NULL);
  280. }
  281. }
  282. __finally {
  283. if (fileHandle != INVALID_HANDLE_VALUE) {
  284. CloseHandle (fileHandle);
  285. }
  286. }
  287. }
  288. __except (EXCEPTION_EXECUTE_HANDLER) {
  289. CloseHandle (fileHandle);
  290. }
  291. return result;
  292. }
  293. BOOL
  294. MdLoadModuleDataW (
  295. IN PCWSTR ModuleName,
  296. OUT PMD_MODULE_IMAGE ModuleImage
  297. )
  298. {
  299. PCSTR moduleNameA;
  300. HANDLE fileHandle;
  301. DWORD bytesRead;
  302. DOS_HEADER dh;
  303. DWORD sign;
  304. PWORD signNE = (PWORD)&sign;
  305. BOOL result = FALSE;
  306. ZeroMemory (ModuleImage, sizeof (MD_MODULE_IMAGE));
  307. fileHandle = CreateFileW (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  308. if (fileHandle == INVALID_HANDLE_VALUE) {
  309. ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
  310. return FALSE;
  311. }
  312. __try {
  313. __try {
  314. if ((!ReadFile (fileHandle, &dh, sizeof (DOS_HEADER), &bytesRead, NULL)) ||
  315. (bytesRead != sizeof (DOS_HEADER))
  316. ) {
  317. __leave;
  318. }
  319. result = TRUE;
  320. if (dh.e_magic != IMAGE_DOS_SIGNATURE) {
  321. ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
  322. __leave;
  323. }
  324. ModuleImage->ModuleType = MODULETYPE_DOS;
  325. if (SetFilePointer (fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) {
  326. __leave;
  327. }
  328. if ((!ReadFile (fileHandle, &sign, sizeof (DWORD), &bytesRead, NULL)) ||
  329. (bytesRead != sizeof (DWORD))
  330. ) {
  331. __leave;
  332. }
  333. CloseHandle (fileHandle);
  334. fileHandle = INVALID_HANDLE_VALUE;
  335. if (sign == IMAGE_PE_SIGNATURE) {
  336. ModuleImage->ModuleType = MODULETYPE_WIN32;
  337. moduleNameA = ConvertWtoA (ModuleName);
  338. if (moduleNameA) {
  339. result = MapAndLoad ((PSTR) moduleNameA, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE);
  340. FreeConvertedStr (moduleNameA);
  341. }
  342. }
  343. if (*signNE == IMAGE_NE_SIGNATURE) {
  344. ModuleImage->ModuleType = MODULETYPE_WIN16;
  345. ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemoryW (
  346. ModuleName,
  347. &ModuleImage->ModuleData.W16Data.FileHandle,
  348. &ModuleImage->ModuleData.W16Data.MapHandle
  349. );
  350. result = (ModuleImage->ModuleData.W16Data.Image != NULL);
  351. }
  352. }
  353. __finally {
  354. if (fileHandle != INVALID_HANDLE_VALUE) {
  355. CloseHandle (fileHandle);
  356. }
  357. }
  358. }
  359. __except (EXCEPTION_EXECUTE_HANDLER) {
  360. CloseHandle (fileHandle);
  361. }
  362. return result;
  363. }
  364. BOOL
  365. MdUnloadModuleDataA (
  366. IN OUT PMD_MODULE_IMAGE ModuleImage
  367. )
  368. {
  369. switch (ModuleImage->ModuleType) {
  370. case MODULETYPE_WIN32:
  371. UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image);
  372. break;
  373. case MODULETYPE_WIN16:
  374. UnmapFile (
  375. (PVOID) ModuleImage->ModuleData.W16Data.Image,
  376. ModuleImage->ModuleData.W16Data.FileHandle,
  377. ModuleImage->ModuleData.W16Data.MapHandle
  378. );
  379. break;
  380. default:;
  381. }
  382. return TRUE;
  383. }
  384. BOOL
  385. MdUnloadModuleDataW (
  386. IN OUT PMD_MODULE_IMAGE ModuleImage
  387. )
  388. {
  389. switch (ModuleImage->ModuleType) {
  390. case MODULETYPE_WIN32:
  391. UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image);
  392. break;
  393. case MODULETYPE_WIN16:
  394. UnmapFile (
  395. (PVOID) ModuleImage->ModuleData.W16Data.Image,
  396. ModuleImage->ModuleData.W16Data.FileHandle,
  397. ModuleImage->ModuleData.W16Data.MapHandle
  398. );
  399. break;
  400. default:;
  401. }
  402. return TRUE;
  403. }
  404. BOOL
  405. MdEnumNextImport16A (
  406. IN OUT PMD_IMPORT_ENUM16A ImportsEnum
  407. )
  408. {
  409. PBYTE currSegmentOffset,importPtr;
  410. PWORD moduleNameOffset;
  411. BOOL itemFound;
  412. PMD_IMPORT_ENUM16_HANDLE handle;
  413. handle = (PMD_IMPORT_ENUM16_HANDLE) ImportsEnum->Handle;
  414. handle->RelocItem ++;
  415. handle->CurrRelocItem ++;
  416. itemFound = FALSE;
  417. while ((handle->CurrSegEntry <= handle->NeHeader->NumEntriesSegTable) && (!itemFound)) {
  418. if (((handle->SegmentEntry->SegmentFlags & SEG_CODE_MASK ) == SEG_CODE ) &&
  419. ((handle->SegmentEntry->SegmentFlags & SEG_RELOC_MASK ) == SEG_RELOC ) &&
  420. ((handle->SegmentEntry->SegmentFlags & SEG_PRELOAD_MASK) == SEG_PRELOAD)
  421. ) {
  422. __try {
  423. while ((handle->CurrRelocItem <= *(handle->CurrNrReloc)) && (!itemFound)) {
  424. if (((handle->RelocItem->AddressType == 0) ||
  425. (handle->RelocItem->AddressType == 2) ||
  426. (handle->RelocItem->AddressType == 3) ||
  427. (handle->RelocItem->AddressType == 5) ||
  428. (handle->RelocItem->AddressType == 11) ||
  429. (handle->RelocItem->AddressType == 13)
  430. ) &&
  431. ((handle->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) ||
  432. (handle->RelocItem->RelocType == RELOC_IMPORTED_NAME )
  433. )
  434. ) {
  435. itemFound = TRUE;
  436. moduleNameOffset = (PWORD) (handle->Image +
  437. handle->DosHeader->e_lfanew +
  438. handle->NeHeader->ModuleTableOffset +
  439. (handle->RelocItem->ModuleOffset - 1) * sizeof (WORD));
  440. importPtr = handle->Image +
  441. handle->DosHeader->e_lfanew +
  442. handle->NeHeader->ImportedTableOffset +
  443. *moduleNameOffset;
  444. strncpy (ImportsEnum->ImportModule, importPtr + 1, (BYTE)importPtr[0]);
  445. ImportsEnum->ImportModule[(BYTE)importPtr[0]] = 0;
  446. if (handle->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) {
  447. ImportsEnum->ImportFunction[0] = 0;
  448. ImportsEnum->ImportFunctionOrd = handle->RelocItem->FunctionOffset;
  449. }
  450. else {
  451. importPtr = handle->Image +
  452. handle->DosHeader->e_lfanew +
  453. handle->NeHeader->ImportedTableOffset +
  454. handle->RelocItem->FunctionOffset;
  455. strncpy (ImportsEnum->ImportFunction, importPtr + 1, (BYTE)importPtr[0]);
  456. ImportsEnum->ImportFunction[(BYTE)importPtr[0]] = 0;
  457. ImportsEnum->ImportFunctionOrd = 0;
  458. }
  459. }
  460. if (!itemFound) {
  461. handle->RelocItem ++;
  462. handle->CurrRelocItem ++;
  463. }
  464. }
  465. }
  466. __except (1) {
  467. itemFound = FALSE;
  468. }
  469. }
  470. if (!itemFound) {
  471. handle->SegmentEntry ++;
  472. handle->CurrSegEntry ++;
  473. currSegmentOffset = handle->Image +
  474. (handle->SegmentEntry->SegmentOffset << handle->NeHeader->ShiftCount);
  475. if (handle->SegmentEntry->SegmentLen == 0) {
  476. currSegmentOffset += 65535;
  477. }
  478. else {
  479. currSegmentOffset += handle->SegmentEntry->SegmentLen;
  480. }
  481. handle->CurrNrReloc = (PWORD) currSegmentOffset;
  482. currSegmentOffset += sizeof(WORD);
  483. handle->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
  484. handle->CurrRelocItem = 1;
  485. }
  486. }
  487. return itemFound;
  488. }
  489. BOOL
  490. MdEnumFirstImport16A (
  491. IN PBYTE ModuleImage,
  492. IN OUT PMD_IMPORT_ENUM16A ImportsEnum
  493. )
  494. {
  495. PMD_IMPORT_ENUM16_HANDLE handle;
  496. PBYTE currSegmentOffset;
  497. ZeroMemory (ImportsEnum, sizeof (MD_IMPORT_ENUM16A));
  498. ImportsEnum->Handle = MemAlloc (g_hHeap, 0, sizeof (MD_IMPORT_ENUM16_HANDLE));
  499. handle = (PMD_IMPORT_ENUM16_HANDLE) ImportsEnum->Handle;
  500. handle->Image = ModuleImage;
  501. handle->DosHeader = (PDOS_HEADER) (handle->Image);
  502. handle->NeHeader = (PNE_HEADER) (handle->Image + handle->DosHeader->e_lfanew);
  503. handle->SegmentEntry = (PNE_SEGMENT_ENTRY) (handle->Image +
  504. handle->DosHeader->e_lfanew +
  505. handle->NeHeader->SegTableOffset
  506. );
  507. handle->CurrSegEntry = 1;
  508. currSegmentOffset = handle->Image +
  509. (handle->SegmentEntry->SegmentOffset << handle->NeHeader->ShiftCount);
  510. if (handle->SegmentEntry->SegmentLen == 0) {
  511. currSegmentOffset += 65535;
  512. }
  513. else {
  514. currSegmentOffset += handle->SegmentEntry->SegmentLen;
  515. }
  516. handle->CurrNrReloc = (PWORD) currSegmentOffset;
  517. currSegmentOffset += sizeof(WORD);
  518. handle->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
  519. handle->CurrRelocItem = 1;
  520. handle->RelocItem --;
  521. handle->CurrRelocItem --;
  522. return MdEnumNextImport16A (ImportsEnum);
  523. }
  524. BOOL
  525. MdAbortImport16EnumA (
  526. IN PMD_IMPORT_ENUM16A ImportsEnum
  527. )
  528. {
  529. if (ImportsEnum->Handle) {
  530. MemFree (g_hHeap, 0, ImportsEnum->Handle);
  531. ImportsEnum->Handle = NULL;
  532. }
  533. return TRUE;
  534. }
  535. BOOL
  536. MdEnumNextImportFunction32A (
  537. IN OUT PMD_IMPORT_ENUM32A ImportsEnum
  538. )
  539. {
  540. PMD_IMPORT_ENUM32_HANDLE handle;
  541. handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
  542. if (handle->ImportFunctionAddr == 0) {
  543. return FALSE;
  544. }
  545. handle->ImageData = (PIMAGE_THUNK_DATA)
  546. ImageRvaToVa (
  547. handle->Image->FileHeader,
  548. handle->Image->MappedAddress,
  549. handle->ImportFunctionAddr,
  550. NULL
  551. );
  552. if (handle->ImageData->u1.AddressOfData) {
  553. handle->ImageName = (PIMAGE_IMPORT_BY_NAME)
  554. ImageRvaToVa (
  555. handle->Image->FileHeader,
  556. handle->Image->MappedAddress,
  557. (DWORD)handle->ImageData->u1.AddressOfData,
  558. NULL
  559. );
  560. if (handle->ImageName) { //import by name
  561. ImportsEnum->ImportFunction = handle->ImageName->Name;
  562. ImportsEnum->ImportFunctionOrd = 0;
  563. }
  564. else { //import by number
  565. ImportsEnum->ImportFunction = NULL;
  566. ImportsEnum->ImportFunctionOrd = (ULONG) handle->ImageData->u1.Ordinal & (~0x80000000);
  567. }
  568. handle->ImportFunctionAddr += 4;
  569. return TRUE;
  570. }
  571. else {
  572. handle->ImportFunctionAddr = 0;
  573. return FALSE;
  574. }
  575. }
  576. BOOL
  577. MdEnumFirstImportFunction32A (
  578. IN OUT PMD_IMPORT_ENUM32A ImportsEnum
  579. )
  580. {
  581. PMD_IMPORT_ENUM32_HANDLE handle;
  582. handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
  583. if ((handle->ImageDescriptor == NULL) ||
  584. (ImportsEnum->ImportModule == NULL)
  585. ) {
  586. return FALSE;
  587. }
  588. handle->ImportFunctionAddr = handle->ImageDescriptor->OriginalFirstThunk;
  589. return MdEnumNextImportFunction32A (ImportsEnum);
  590. }
  591. BOOL
  592. MdEnumNextImportModule32A (
  593. IN OUT PMD_IMPORT_ENUM32A ImportsEnum
  594. )
  595. {
  596. PMD_IMPORT_ENUM32_HANDLE handle;
  597. handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
  598. if (handle->ImageDescriptor == NULL) {
  599. return FALSE;
  600. }
  601. handle->ImageDescriptor ++;
  602. if (handle->ImageDescriptor->Name == 0) {
  603. return FALSE;
  604. }
  605. ImportsEnum->ImportModule = (PCSTR)
  606. ImageRvaToVa (
  607. handle->Image->FileHeader,
  608. handle->Image->MappedAddress,
  609. handle->ImageDescriptor->Name,
  610. NULL
  611. );
  612. return (ImportsEnum->ImportModule != NULL);
  613. }
  614. BOOL
  615. MdEnumFirstImportModule32A (
  616. IN PLOADED_IMAGE ModuleImage,
  617. IN OUT PMD_IMPORT_ENUM32A ImportsEnum
  618. )
  619. {
  620. PMD_IMPORT_ENUM32_HANDLE handle;
  621. ULONG imageSize;
  622. ZeroMemory (ImportsEnum, sizeof (MD_IMPORT_ENUM32A));
  623. ImportsEnum->Handle = MemAlloc (g_hHeap, 0, sizeof (MD_IMPORT_ENUM32_HANDLE));
  624. handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
  625. handle->Image = ModuleImage;
  626. handle->ImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)
  627. ImageDirectoryEntryToData (
  628. ModuleImage->MappedAddress,
  629. FALSE,
  630. IMAGE_DIRECTORY_ENTRY_IMPORT,
  631. &imageSize
  632. );
  633. if (!handle->ImageDescriptor) {
  634. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load import directory for %s", ModuleImage->ModuleName));
  635. return FALSE;
  636. }
  637. if (handle->ImageDescriptor->Name == 0) {
  638. return FALSE;
  639. }
  640. ImportsEnum->ImportModule = (PCSTR)
  641. ImageRvaToVa (
  642. handle->Image->FileHeader,
  643. handle->Image->MappedAddress,
  644. handle->ImageDescriptor->Name,
  645. NULL
  646. );
  647. return (ImportsEnum->ImportModule != NULL);
  648. }
  649. BOOL
  650. MdAbortImport32EnumA (
  651. IN PMD_IMPORT_ENUM32A ImportsEnum
  652. )
  653. {
  654. if (ImportsEnum->Handle) {
  655. MemFree (g_hHeap, 0, ImportsEnum->Handle);
  656. ImportsEnum->Handle = NULL;
  657. }
  658. return TRUE;
  659. }
  660. DWORD
  661. MdGetModuleTypeA (
  662. IN PCSTR ModuleName
  663. )
  664. {
  665. MD_MODULE_IMAGE moduleImage;
  666. DWORD result = MODULETYPE_UNKNOWN;
  667. __try {
  668. if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
  669. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
  670. __leave;
  671. }
  672. result = moduleImage.ModuleType;
  673. }
  674. __finally {
  675. MdUnloadModuleDataA (&moduleImage);
  676. }
  677. return result;
  678. }
  679. DWORD
  680. MdGetModuleTypeW (
  681. IN PCWSTR ModuleName
  682. )
  683. {
  684. MD_MODULE_IMAGE moduleImage;
  685. DWORD result = MODULETYPE_UNKNOWN;
  686. __try {
  687. if (!MdLoadModuleDataW (ModuleName, &moduleImage)) {
  688. DEBUGMSGW((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
  689. __leave;
  690. }
  691. result = moduleImage.ModuleType;
  692. }
  693. __finally {
  694. MdUnloadModuleDataW (&moduleImage);
  695. }
  696. return result;
  697. }
  698. PCSTR
  699. MdGet16ModuleDescriptionA (
  700. IN PCSTR ModuleName
  701. )
  702. {
  703. MD_MODULE_IMAGE moduleImage;
  704. PSTR result = NULL;
  705. PDOS_HEADER dosHeader;
  706. PNE_HEADER neHeader;
  707. PBYTE size;
  708. __try {
  709. if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
  710. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
  711. __leave;
  712. }
  713. if (moduleImage.ModuleType != MODULETYPE_WIN16) {
  714. __leave;
  715. }
  716. __try {
  717. dosHeader = (PDOS_HEADER) (moduleImage.ModuleData.W16Data.Image);
  718. neHeader = (PNE_HEADER) (moduleImage.ModuleData.W16Data.Image + dosHeader->e_lfanew);
  719. size = (PBYTE) (moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset);
  720. if (*size == 0) {
  721. __leave;
  722. }
  723. result = AllocPathStringA (*size + 1);
  724. strncpy (result, moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset + 1, *size);
  725. result [*size] = 0;
  726. }
  727. __except (1) {
  728. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
  729. if (result != NULL) {
  730. FreePathStringA (result);
  731. result = NULL;
  732. }
  733. __leave;
  734. }
  735. }
  736. __finally {
  737. MdUnloadModuleDataA (&moduleImage);
  738. }
  739. return result;
  740. }
  741. PCWSTR
  742. MdGet16ModuleDescriptionW (
  743. IN PCWSTR ModuleName
  744. )
  745. {
  746. MD_MODULE_IMAGE moduleImage;
  747. PSTR resultA = NULL;
  748. PCWSTR tempResult = NULL;
  749. PCWSTR result = NULL;
  750. PDOS_HEADER dosHeader;
  751. PNE_HEADER neHeader;
  752. PBYTE size;
  753. __try {
  754. if (!MdLoadModuleDataW (ModuleName, &moduleImage)) {
  755. DEBUGMSGW((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
  756. __leave;
  757. }
  758. if (moduleImage.ModuleType != MODULETYPE_WIN16) {
  759. __leave;
  760. }
  761. __try {
  762. dosHeader = (PDOS_HEADER) (moduleImage.ModuleData.W16Data.Image);
  763. neHeader = (PNE_HEADER) (moduleImage.ModuleData.W16Data.Image + dosHeader->e_lfanew);
  764. size = (PBYTE) (moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset);
  765. if (*size == 0) {
  766. __leave;
  767. }
  768. resultA = AllocPathStringA (*size + 1);
  769. if (resultA) {
  770. strncpy (resultA, moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset + 1, *size);
  771. resultA [*size] = 0;
  772. tempResult = ConvertAtoW (resultA);
  773. if (tempResult) {
  774. result = DuplicatePathStringW (tempResult, 0);
  775. FreeConvertedStr (tempResult);
  776. tempResult = NULL;
  777. }
  778. FreePathStringA (resultA);
  779. resultA = NULL;
  780. }
  781. }
  782. __except (1) {
  783. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
  784. if (result != NULL) {
  785. FreePathStringW (result);
  786. result = NULL;
  787. }
  788. if (tempResult != NULL) {
  789. FreeConvertedStr (tempResult);
  790. tempResult = NULL;
  791. }
  792. if (resultA != NULL) {
  793. FreePathStringA (resultA);
  794. resultA = NULL;
  795. }
  796. __leave;
  797. }
  798. }
  799. __finally {
  800. MdUnloadModuleDataW (&moduleImage);
  801. }
  802. return result;
  803. }
  804. PIMAGE_NT_HEADERS
  805. pGetImageNtHeader (
  806. IN PVOID Base
  807. )
  808. /*++
  809. Routine Description:
  810. This function returns the address of the NT Header.
  811. Arguments:
  812. Base - Supplies the base of the image.
  813. Return Value:
  814. Returns the address of the NT Header.
  815. --*/
  816. {
  817. PIMAGE_NT_HEADERS NtHeaders;
  818. if (Base != NULL && Base != (PVOID)-1) {
  819. if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) {
  820. NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
  821. if (NtHeaders->Signature == IMAGE_NT_SIGNATURE) {
  822. return NtHeaders;
  823. }
  824. }
  825. }
  826. return NULL;
  827. }
  828. ULONG
  829. MdGetPECheckSumA (
  830. IN PCSTR ModuleName
  831. )
  832. {
  833. MD_MODULE_IMAGE moduleImage;
  834. ULONG result = 0;
  835. PIMAGE_NT_HEADERS NtHeaders;
  836. __try {
  837. if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
  838. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
  839. __leave;
  840. }
  841. if (moduleImage.ModuleType != MODULETYPE_WIN32) {
  842. __leave;
  843. }
  844. __try {
  845. NtHeaders = pGetImageNtHeader(moduleImage.ModuleData.W32Data.Image.MappedAddress);
  846. if (NtHeaders) {
  847. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  848. result = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum;
  849. } else
  850. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  851. result = ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum;
  852. }
  853. }
  854. }
  855. __except (1) {
  856. DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
  857. result = 0;
  858. __leave;
  859. }
  860. }
  861. __finally {
  862. MdUnloadModuleDataA (&moduleImage);
  863. }
  864. return result;
  865. }
  866. DWORD
  867. MdGetCheckSumA (
  868. IN PCSTR ModuleName
  869. )
  870. /*++
  871. Routine Description:
  872. GetCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
  873. the chunk are modified if the file size is too small.
  874. Arguments:
  875. ModuleName - Specifies the file to compute the check sum for.
  876. Return value:
  877. The computed checksum
  878. --*/
  879. {
  880. INT i,size = 4096;
  881. DWORD startAddr = 512;
  882. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  883. PCHAR buffer = NULL;
  884. DWORD checkSum = 0;
  885. DWORD dontCare;
  886. WIN32_FIND_DATAA findData;
  887. if (!DoesFileExistExA (ModuleName, &findData)) {
  888. return checkSum;
  889. }
  890. if (findData.nFileSizeLow < (ULONG)size) {
  891. //
  892. // File size is less than 4096. We set the start address to 0 and set the size for the checksum
  893. // to the actual file size.
  894. //
  895. startAddr = 0;
  896. size = findData.nFileSizeLow;
  897. }
  898. else
  899. if (startAddr + size > findData.nFileSizeLow) {
  900. //
  901. // File size is too small. We set the start address so that size of checksum can be 4096 bytes
  902. //
  903. startAddr = findData.nFileSizeLow - size;
  904. }
  905. if (size <= 3) {
  906. //
  907. // we need at least 3 bytes to be able to do something here.
  908. //
  909. return 0;
  910. }
  911. __try {
  912. buffer = HeapAlloc (g_hHeap, 0, size);
  913. if (buffer == NULL) {
  914. __leave;
  915. }
  916. fileHandle = CreateFileA (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  917. if (fileHandle == INVALID_HANDLE_VALUE) {
  918. __leave;
  919. }
  920. if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
  921. __leave;
  922. }
  923. if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
  924. __leave;
  925. }
  926. for (i = 0; i<(size - 3); i+=4) {
  927. checkSum += *((PDWORD) (buffer + i));
  928. checkSum = _rotr (checkSum ,1);
  929. }
  930. }
  931. __finally {
  932. if (fileHandle != INVALID_HANDLE_VALUE) {
  933. CloseHandle (fileHandle);
  934. }
  935. if (buffer != NULL) {
  936. HeapFree (g_hHeap, 0, buffer);
  937. }
  938. }
  939. return checkSum;
  940. }
  941. DWORD
  942. MdGetCheckSumW (
  943. IN PCWSTR ModuleName
  944. )
  945. /*++
  946. Routine Description:
  947. GetCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
  948. the chunk are modified if the file size is too small.
  949. Arguments:
  950. ModuleName - Specifies the file to compute the check sum for.
  951. Return value:
  952. The computed checksum
  953. --*/
  954. {
  955. INT i,size = 4096;
  956. DWORD startAddr = 512;
  957. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  958. PCHAR buffer = NULL;
  959. DWORD checkSum = 0;
  960. DWORD dontCare;
  961. WIN32_FIND_DATAW findData;
  962. if (!DoesFileExistExW (ModuleName, &findData)) {
  963. return checkSum;
  964. }
  965. if (findData.nFileSizeLow < (ULONG)size) {
  966. //
  967. // File size is less than 4096. We set the start address to 0 and set the size for the checksum
  968. // to the actual file size.
  969. //
  970. startAddr = 0;
  971. size = findData.nFileSizeLow;
  972. }
  973. else
  974. if (startAddr + size > findData.nFileSizeLow) {
  975. //
  976. // File size is too small. We set the start address so that size of checksum can be 4096 bytes
  977. //
  978. startAddr = findData.nFileSizeLow - size;
  979. }
  980. if (size <= 3) {
  981. //
  982. // we need at least 3 bytes to be able to do something here.
  983. //
  984. return 0;
  985. }
  986. __try {
  987. buffer = HeapAlloc (g_hHeap, 0, size);
  988. if (buffer == NULL) {
  989. __leave;
  990. }
  991. fileHandle = CreateFileW (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  992. if (fileHandle == INVALID_HANDLE_VALUE) {
  993. __leave;
  994. }
  995. if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
  996. __leave;
  997. }
  998. if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
  999. __leave;
  1000. }
  1001. for (i = 0; i<(size - 3); i+=4) {
  1002. checkSum += *((PDWORD) (buffer + i));
  1003. checkSum = _rotr (checkSum ,1);
  1004. }
  1005. }
  1006. __finally {
  1007. if (fileHandle != INVALID_HANDLE_VALUE) {
  1008. CloseHandle (fileHandle);
  1009. }
  1010. if (buffer != NULL) {
  1011. HeapFree (g_hHeap, 0, buffer);
  1012. }
  1013. }
  1014. return checkSum;
  1015. }
  1016. VOID
  1017. DestroyAnsiResourceId (
  1018. IN PCSTR AnsiId
  1019. )
  1020. {
  1021. if (HIWORD (AnsiId)) {
  1022. FreeConvertedStr (AnsiId);
  1023. }
  1024. }
  1025. VOID
  1026. DestroyUnicodeResourceId (
  1027. IN PCWSTR UnicodeId
  1028. )
  1029. {
  1030. if (HIWORD (UnicodeId)) {
  1031. FreeConvertedStr (UnicodeId);
  1032. }
  1033. }
  1034. BOOL
  1035. NeLoadHeader (
  1036. IN HANDLE File,
  1037. OUT PNE_INFO_BLOCK Header
  1038. )
  1039. {
  1040. DOS_HEADER dh;
  1041. LONG rc = ERROR_BAD_FORMAT;
  1042. BOOL b = FALSE;
  1043. __try {
  1044. SetFilePointer (File, 0, NULL, FILE_BEGIN);
  1045. if (!BfReadFile (File, (PBYTE)(&dh), sizeof (DOS_HEADER))) {
  1046. __leave;
  1047. }
  1048. if (dh.e_magic != ('M' + 'Z' * 256)) {
  1049. __leave;
  1050. }
  1051. SetFilePointer (File, dh.e_lfanew, NULL, FILE_BEGIN);
  1052. if (!BfReadFile (File, (PBYTE)Header, sizeof (NE_INFO_BLOCK))) {
  1053. __leave;
  1054. }
  1055. if (Header->Signature != ('N' + 'E' * 256) &&
  1056. Header->Signature != ('L' + 'E' * 256)
  1057. ) {
  1058. if (Header->Signature == ('P' + 'E' * 256)) {
  1059. rc = ERROR_BAD_EXE_FORMAT;
  1060. } else {
  1061. rc = ERROR_INVALID_EXE_SIGNATURE;
  1062. }
  1063. DEBUGMSG ((DBG_NAUSEA, "Header signature is %c%c", Header->Signature & 0xff, Header->Signature >> 8));
  1064. __leave;
  1065. }
  1066. SetFilePointer (File, (DWORD) dh.e_lfanew, NULL, FILE_BEGIN);
  1067. b = TRUE;
  1068. }
  1069. __finally {
  1070. if (!b) {
  1071. SetLastError (rc);
  1072. }
  1073. }
  1074. return b;
  1075. }
  1076. DWORD
  1077. pComputeSizeOfTypeInfo (
  1078. IN PNE_RES_TYPEINFO TypeInfo
  1079. )
  1080. {
  1081. return sizeof (NE_RES_TYPEINFO) + TypeInfo->ResourceCount * sizeof (NE_RES_NAMEINFO);
  1082. }
  1083. PNE_RES_TYPEINFO
  1084. pReadNextTypeInfoStruct (
  1085. IN HANDLE File,
  1086. IN PMHANDLE Pool
  1087. )
  1088. {
  1089. WORD Type;
  1090. WORD ResCount;
  1091. NE_RES_TYPEINFO TypeInfo;
  1092. PNE_RES_TYPEINFO ReturnInfo = NULL;
  1093. DWORD Size;
  1094. if (!BfReadFile (File, (PBYTE)(&Type), sizeof (WORD))) {
  1095. return NULL;
  1096. }
  1097. if (!Type) {
  1098. return NULL;
  1099. }
  1100. if (!BfReadFile (File, (PBYTE)(&ResCount), sizeof (WORD))) {
  1101. return NULL;
  1102. }
  1103. TypeInfo.TypeId = Type;
  1104. TypeInfo.ResourceCount = ResCount;
  1105. if (!BfReadFile (File, (PBYTE)(&TypeInfo.Reserved), sizeof (DWORD))) {
  1106. return NULL;
  1107. }
  1108. Size = sizeof (NE_RES_NAMEINFO) * ResCount;
  1109. ReturnInfo = (PNE_RES_TYPEINFO) PmGetMemory (Pool, Size + sizeof (TypeInfo));
  1110. if (!ReturnInfo) {
  1111. return NULL;
  1112. }
  1113. CopyMemory (ReturnInfo, &TypeInfo, sizeof (TypeInfo));
  1114. if (!BfReadFile (File, (PBYTE) ReturnInfo + sizeof (TypeInfo), Size)) {
  1115. return NULL;
  1116. }
  1117. return ReturnInfo;
  1118. }
  1119. BOOL
  1120. pReadTypeInfoArray (
  1121. IN HANDLE File,
  1122. IN OUT PGROWLIST TypeInfoList
  1123. )
  1124. {
  1125. PNE_RES_TYPEINFO TypeInfo;
  1126. DWORD Size;
  1127. PMHANDLE TempPool;
  1128. BOOL b = FALSE;
  1129. TempPool = PmCreatePool();
  1130. if (!TempPool) {
  1131. return FALSE;
  1132. }
  1133. __try {
  1134. TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
  1135. while (TypeInfo) {
  1136. Size = pComputeSizeOfTypeInfo (TypeInfo);
  1137. if (!GlAppend (TypeInfoList, (PBYTE) TypeInfo, Size)) {
  1138. __leave;
  1139. }
  1140. TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
  1141. }
  1142. b = TRUE;
  1143. }
  1144. __finally {
  1145. PmDestroyPool (TempPool);
  1146. }
  1147. return b;
  1148. }
  1149. BOOL
  1150. pReadStringArrayA (
  1151. IN HANDLE File,
  1152. IN OUT PGROWLIST GrowList
  1153. )
  1154. {
  1155. BYTE Size;
  1156. CHAR Name[256];
  1157. if (!BfReadFile (File, (PBYTE)(&Size), sizeof (BYTE))) {
  1158. return FALSE;
  1159. }
  1160. while (Size) {
  1161. if (!BfReadFile (File, Name, (DWORD) Size)) {
  1162. return FALSE;
  1163. }
  1164. Name[Size] = 0;
  1165. GlAppendStringA (GrowList, Name);
  1166. if (!BfReadFile (File, (PBYTE)(&Size), sizeof (BYTE))) {
  1167. return FALSE;
  1168. }
  1169. }
  1170. return TRUE;
  1171. }
  1172. BOOL
  1173. NeLoadResources (
  1174. IN HANDLE File,
  1175. OUT PNE_RESOURCES Resources
  1176. )
  1177. {
  1178. NE_INFO_BLOCK Header;
  1179. ZeroMemory (Resources, sizeof (NE_RESOURCES));
  1180. if (!NeLoadHeader (File, &Header)) {
  1181. return FALSE;
  1182. }
  1183. //
  1184. // Read in NE_RESOURCES struct
  1185. //
  1186. SetFilePointer (File, (DWORD) Header.OffsetToResourceTable, NULL, FILE_CURRENT);
  1187. if (!BfReadFile (File, (PBYTE)(&Resources->AlignShift), sizeof (WORD))) {
  1188. return FALSE;
  1189. }
  1190. // Array of NE_RES_TYPEINFO structs
  1191. if (!pReadTypeInfoArray (File, &Resources->TypeInfoArray)) {
  1192. return FALSE;
  1193. }
  1194. // Resource names
  1195. if (!pReadStringArrayA (File, &Resources->ResourceNames)) {
  1196. return FALSE;
  1197. }
  1198. return TRUE;
  1199. }
  1200. VOID
  1201. NeFreeResources (
  1202. PNE_RESOURCES Resources
  1203. )
  1204. {
  1205. GlFree (&Resources->TypeInfoArray);
  1206. GlFree (&Resources->ResourceNames);
  1207. ZeroMemory (Resources, sizeof (NE_RESOURCES));
  1208. }
  1209. HANDLE
  1210. NeOpenFileA (
  1211. PCSTR FileName
  1212. )
  1213. {
  1214. PNE_HANDLE NeHandle;
  1215. BOOL b = FALSE;
  1216. NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
  1217. __try {
  1218. NeHandle->ResourcePool = PmCreatePool();
  1219. if (!NeHandle->ResourcePool) {
  1220. __leave;
  1221. }
  1222. NeHandle->File = CreateFileA (
  1223. FileName,
  1224. GENERIC_READ,
  1225. FILE_SHARE_READ,
  1226. NULL,
  1227. OPEN_EXISTING,
  1228. FILE_ATTRIBUTE_NORMAL,
  1229. NULL
  1230. );
  1231. if (NeHandle->File == INVALID_HANDLE_VALUE) {
  1232. __leave;
  1233. }
  1234. if (!NeLoadHeader (NeHandle->File, &NeHandle->Header)) {
  1235. __leave;
  1236. }
  1237. NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
  1238. b = TRUE;
  1239. }
  1240. __finally {
  1241. if (!b) {
  1242. PushError();
  1243. if (NeHandle->ResourcePool) {
  1244. PmDestroyPool (NeHandle->ResourcePool);
  1245. }
  1246. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  1247. CloseHandle (NeHandle->File);
  1248. }
  1249. MemFree (g_hHeap, 0, NeHandle);
  1250. NeHandle = NULL;
  1251. PopError();
  1252. }
  1253. }
  1254. return (HANDLE) NeHandle;
  1255. }
  1256. HANDLE
  1257. NeOpenFileW (
  1258. PCWSTR FileName
  1259. )
  1260. {
  1261. PNE_HANDLE NeHandle;
  1262. BOOL b = FALSE;
  1263. NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
  1264. __try {
  1265. NeHandle->ResourcePool = PmCreatePool();
  1266. if (!NeHandle->ResourcePool) {
  1267. __leave;
  1268. }
  1269. NeHandle->File = CreateFileW (
  1270. FileName,
  1271. GENERIC_READ,
  1272. FILE_SHARE_READ,
  1273. NULL,
  1274. OPEN_EXISTING,
  1275. FILE_ATTRIBUTE_NORMAL,
  1276. NULL
  1277. );
  1278. if (NeHandle->File == INVALID_HANDLE_VALUE) {
  1279. __leave;
  1280. }
  1281. if (!NeLoadHeader (NeHandle->File, &NeHandle->Header)) {
  1282. __leave;
  1283. }
  1284. NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
  1285. b = TRUE;
  1286. }
  1287. __finally {
  1288. if (!b) {
  1289. PushError();
  1290. if (NeHandle->ResourcePool) {
  1291. PmDestroyPool (NeHandle->ResourcePool);
  1292. }
  1293. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  1294. CloseHandle (NeHandle->File);
  1295. }
  1296. MemFree (g_hHeap, 0, NeHandle);
  1297. NeHandle = NULL;
  1298. PopError();
  1299. }
  1300. }
  1301. return (HANDLE) NeHandle;
  1302. }
  1303. VOID
  1304. NeCloseFile (
  1305. HANDLE Handle
  1306. )
  1307. {
  1308. PNE_HANDLE NeHandle;
  1309. NeHandle = (PNE_HANDLE) Handle;
  1310. if (!NeHandle) {
  1311. return;
  1312. }
  1313. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  1314. CloseHandle (NeHandle->File);
  1315. }
  1316. if (NeHandle->ResourcesLoaded) {
  1317. NeFreeResources (&NeHandle->Resources);
  1318. }
  1319. PmDestroyPool (NeHandle->ResourcePool);
  1320. MemFree (g_hHeap, 0, NeHandle);
  1321. }
  1322. PCSTR
  1323. pConvertUnicodeResourceId (
  1324. IN PCWSTR ResId
  1325. )
  1326. {
  1327. if (HIWORD (ResId)) {
  1328. return ConvertWtoA (ResId);
  1329. }
  1330. return (PCSTR) ResId;
  1331. }
  1332. PCSTR
  1333. pDecodeIdReferenceInString (
  1334. IN PCSTR ResName
  1335. )
  1336. {
  1337. if (HIWORD (ResName) && ResName[0] == '#') {
  1338. return (PCSTR) (ULONG_PTR) atoi (&ResName[1]);
  1339. }
  1340. return ResName;
  1341. }
  1342. BOOL
  1343. pNeLoadResourcesFromHandle (
  1344. IN PNE_HANDLE NeHandle
  1345. )
  1346. {
  1347. if (NeHandle->ResourcesLoaded) {
  1348. return TRUE;
  1349. }
  1350. if (!NeLoadResources (NeHandle->File, &NeHandle->Resources)) {
  1351. return FALSE;
  1352. }
  1353. NeHandle->ResourcesLoaded = TRUE;
  1354. return TRUE;
  1355. }
  1356. BOOL
  1357. pLoadNeResourceName (
  1358. OUT PSTR ResName,
  1359. IN HANDLE File,
  1360. IN DWORD StringOffset
  1361. )
  1362. {
  1363. BYTE ResNameSize;
  1364. SetFilePointer (File, StringOffset, NULL, FILE_BEGIN);
  1365. if (!BfReadFile (File, (PBYTE)(&ResNameSize), 1)) {
  1366. return FALSE;
  1367. }
  1368. ResName[ResNameSize] = 0;
  1369. return BfReadFile (File, ResName, ResNameSize);
  1370. }
  1371. BOOL
  1372. pNeEnumResourceTypesEx (
  1373. IN HANDLE Handle,
  1374. IN ENUMRESTYPEPROCEXA EnumFunc,
  1375. IN LONG_PTR lParam,
  1376. IN BOOL ExFunctionality,
  1377. IN BOOL UnicodeProc
  1378. )
  1379. {
  1380. PNE_HANDLE NeHandle;
  1381. PNE_RES_TYPEINFO TypeInfo;
  1382. INT Count;
  1383. INT i;
  1384. DWORD StringOffset;
  1385. CHAR ResName[256];
  1386. ENUMRESTYPEPROCA EnumFunc2 = (ENUMRESTYPEPROCA) EnumFunc;
  1387. ENUMRESTYPEPROCEXW EnumFuncW = (ENUMRESTYPEPROCEXW) EnumFunc;
  1388. ENUMRESTYPEPROCW EnumFunc2W = (ENUMRESTYPEPROCW) EnumFunc;
  1389. PWSTR UnicodeResName = NULL;
  1390. //
  1391. // Make sure resources are loaded
  1392. //
  1393. NeHandle = (PNE_HANDLE) Handle;
  1394. if (!NeHandle || !EnumFunc) {
  1395. SetLastError (ERROR_INVALID_PARAMETER);
  1396. return FALSE;
  1397. }
  1398. if (!pNeLoadResourcesFromHandle (NeHandle)) {
  1399. return FALSE;
  1400. }
  1401. //
  1402. // Enumerate all resource types
  1403. //
  1404. Count = GlGetSize (&NeHandle->Resources.TypeInfoArray);
  1405. for (i = 0 ; i < Count ; i++) {
  1406. TypeInfo = (PNE_RES_TYPEINFO) GlGetItem (&NeHandle->Resources.TypeInfoArray, i);
  1407. if (TypeInfo->TypeId & 0x8000) {
  1408. if (ExFunctionality) {
  1409. if (UnicodeProc) {
  1410. if (!EnumFuncW (Handle, (PWSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
  1411. break;
  1412. }
  1413. } else {
  1414. if (!EnumFunc (Handle, (PSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
  1415. break;
  1416. }
  1417. }
  1418. } else {
  1419. if (UnicodeProc) {
  1420. if (!EnumFunc2W (Handle, (PWSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
  1421. break;
  1422. }
  1423. } else {
  1424. if (!EnumFunc2 (Handle, (PSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
  1425. break;
  1426. }
  1427. }
  1428. }
  1429. } else {
  1430. //
  1431. // TypeInfo->TypeId gives an offset to the resource string name,
  1432. // relative to the start of the resource table
  1433. //
  1434. StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + TypeInfo->TypeId;
  1435. pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
  1436. if (UnicodeProc) {
  1437. UnicodeResName = (PWSTR) ConvertAtoW (ResName);
  1438. }
  1439. if (ExFunctionality) {
  1440. if (UnicodeProc) {
  1441. if (!EnumFuncW (Handle, UnicodeResName, lParam, TypeInfo)) {
  1442. break;
  1443. }
  1444. } else {
  1445. if (!EnumFunc (Handle, ResName, lParam, TypeInfo)) {
  1446. break;
  1447. }
  1448. }
  1449. } else {
  1450. if (UnicodeProc) {
  1451. if (!EnumFunc2W (Handle, UnicodeResName, lParam)) {
  1452. break;
  1453. }
  1454. } else {
  1455. if (!EnumFunc2 (Handle, ResName, lParam)) {
  1456. break;
  1457. }
  1458. }
  1459. }
  1460. }
  1461. }
  1462. return TRUE;
  1463. }
  1464. BOOL
  1465. NeEnumResourceTypesA (
  1466. IN HANDLE Handle,
  1467. IN ENUMRESTYPEPROCA EnumFunc,
  1468. IN LONG_PTR lParam
  1469. )
  1470. {
  1471. return pNeEnumResourceTypesEx (
  1472. Handle,
  1473. (ENUMRESTYPEPROCEXA) EnumFunc,
  1474. lParam,
  1475. FALSE, // no ex functionality
  1476. FALSE // ANSI enum proc
  1477. );
  1478. }
  1479. BOOL
  1480. NeEnumResourceTypesW (
  1481. IN HANDLE Handle,
  1482. IN ENUMRESTYPEPROCW EnumFunc,
  1483. IN LONG_PTR lParam
  1484. )
  1485. {
  1486. return pNeEnumResourceTypesEx (
  1487. Handle,
  1488. (ENUMRESTYPEPROCEXA) EnumFunc,
  1489. lParam,
  1490. FALSE, // no ex functionality
  1491. TRUE // UNICODE enum proc
  1492. );
  1493. }
  1494. BOOL
  1495. pEnumTypeForNameSearchProcA (
  1496. IN HANDLE Handle,
  1497. IN PCSTR Type,
  1498. IN LONG_PTR lParam,
  1499. IN PNE_RES_TYPEINFO TypeInfo
  1500. )
  1501. {
  1502. PTYPESEARCHDATAA Data;
  1503. Data = (PTYPESEARCHDATAA) lParam;
  1504. //
  1505. // Compare type
  1506. //
  1507. if (HIWORD (Data->TypeToFind) == 0) {
  1508. if (Type != Data->TypeToFind) {
  1509. return TRUE;
  1510. }
  1511. } else {
  1512. if (HIWORD (Type) == 0) {
  1513. return TRUE;
  1514. }
  1515. if (!StringIMatchA (Type, Data->TypeToFind)) {
  1516. return TRUE;
  1517. }
  1518. }
  1519. //
  1520. // Type found
  1521. //
  1522. Data->OutboundTypeInfo = TypeInfo;
  1523. Data->Found = TRUE;
  1524. return FALSE;
  1525. }
  1526. BOOL
  1527. pNeEnumResourceNamesEx (
  1528. IN HANDLE Handle,
  1529. IN PCSTR Type,
  1530. IN ENUMRESNAMEPROCEXA EnumFunc,
  1531. IN LONG_PTR lParam,
  1532. IN BOOL ExFunctionality,
  1533. IN BOOL UnicodeProc
  1534. )
  1535. {
  1536. PNE_HANDLE NeHandle;
  1537. PNE_RES_TYPEINFO TypeInfo;
  1538. PNE_RES_NAMEINFO NameInfo;
  1539. TYPESEARCHDATAA Data;
  1540. WORD w;
  1541. DWORD StringOffset;
  1542. CHAR ResName[256];
  1543. ENUMRESNAMEPROCA EnumFunc2 = (ENUMRESNAMEPROCA) EnumFunc;
  1544. ENUMRESNAMEPROCEXW EnumFuncW = (ENUMRESNAMEPROCEXW) EnumFunc;
  1545. ENUMRESNAMEPROCW EnumFunc2W = (ENUMRESNAMEPROCW) EnumFunc;
  1546. PCWSTR UnicodeType = NULL;
  1547. PCWSTR UnicodeResName = NULL;
  1548. Type = pDecodeIdReferenceInString (Type);
  1549. //
  1550. // Make sure resources are loaded
  1551. //
  1552. NeHandle = (PNE_HANDLE) Handle;
  1553. if (!NeHandle || !EnumFunc) {
  1554. SetLastError (ERROR_INVALID_PARAMETER);
  1555. return FALSE;
  1556. }
  1557. if (!pNeLoadResourcesFromHandle (NeHandle)) {
  1558. return FALSE;
  1559. }
  1560. //
  1561. // Locate type
  1562. //
  1563. ZeroMemory (&Data, sizeof (Data));
  1564. Data.TypeToFind = Type;
  1565. if (!pNeEnumResourceTypesEx (
  1566. Handle,
  1567. pEnumTypeForNameSearchProcA,
  1568. (ULONG_PTR) &Data,
  1569. TRUE, // ex functionality
  1570. FALSE // ANSI enum proc
  1571. )) {
  1572. SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
  1573. return FALSE;
  1574. }
  1575. if (!Data.Found) {
  1576. SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
  1577. return FALSE;
  1578. }
  1579. TypeInfo = Data.OutboundTypeInfo;
  1580. if (UnicodeProc) {
  1581. if (HIWORD (Type)) {
  1582. UnicodeType = ConvertAtoW (Type);
  1583. } else {
  1584. UnicodeType = (PCWSTR) Type;
  1585. }
  1586. }
  1587. //
  1588. // Enumerate the resource names
  1589. //
  1590. NameInfo = TypeInfo->NameInfo;
  1591. for (w = 0 ; w < TypeInfo->ResourceCount ; w++) {
  1592. if (NameInfo->Id & 0x8000) {
  1593. if (ExFunctionality) {
  1594. if (UnicodeProc) {
  1595. if (!EnumFuncW (
  1596. Handle,
  1597. UnicodeType,
  1598. (PWSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
  1599. lParam,
  1600. TypeInfo,
  1601. NameInfo
  1602. )) {
  1603. break;
  1604. }
  1605. } else {
  1606. if (!EnumFunc (
  1607. Handle,
  1608. Type,
  1609. (PSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
  1610. lParam,
  1611. TypeInfo,
  1612. NameInfo
  1613. )) {
  1614. break;
  1615. }
  1616. }
  1617. } else {
  1618. if (UnicodeProc) {
  1619. if (!EnumFunc2W (
  1620. Handle,
  1621. UnicodeType,
  1622. (PWSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
  1623. lParam
  1624. )) {
  1625. break;
  1626. }
  1627. } else {
  1628. if (!EnumFunc2 (
  1629. Handle,
  1630. Type,
  1631. (PSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
  1632. lParam
  1633. )) {
  1634. break;
  1635. }
  1636. }
  1637. }
  1638. } else {
  1639. //
  1640. // TypeInfo->TypeId gives an offset to the resource string name,
  1641. // relative to the start of the resource table
  1642. //
  1643. StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + NameInfo->Id;
  1644. pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
  1645. if (UnicodeProc) {
  1646. UnicodeResName = ConvertAtoW (ResName);
  1647. }
  1648. if (ExFunctionality) {
  1649. if (UnicodeProc) {
  1650. if (!EnumFuncW (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam, TypeInfo, NameInfo)) {
  1651. break;
  1652. }
  1653. } else {
  1654. if (!EnumFunc (Handle, Type, ResName, lParam, TypeInfo, NameInfo)) {
  1655. break;
  1656. }
  1657. }
  1658. } else {
  1659. if (UnicodeProc) {
  1660. if (!EnumFunc2W (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam)) {
  1661. break;
  1662. }
  1663. } else {
  1664. if (!EnumFunc2 (Handle, Type, ResName, lParam)) {
  1665. break;
  1666. }
  1667. }
  1668. }
  1669. if (UnicodeProc) {
  1670. FreeConvertedStr (UnicodeResName);
  1671. }
  1672. }
  1673. NameInfo++;
  1674. }
  1675. if (UnicodeProc) {
  1676. DestroyUnicodeResourceId (UnicodeType);
  1677. }
  1678. return TRUE;
  1679. }
  1680. BOOL
  1681. NeEnumResourceNamesA (
  1682. IN HANDLE Handle,
  1683. IN PCSTR Type,
  1684. IN ENUMRESNAMEPROCA EnumFunc,
  1685. IN LONG_PTR lParam
  1686. )
  1687. {
  1688. return pNeEnumResourceNamesEx (
  1689. Handle,
  1690. Type,
  1691. (ENUMRESNAMEPROCEXA) EnumFunc,
  1692. lParam,
  1693. FALSE, // no ex functionality
  1694. FALSE // ANSI enum proc
  1695. );
  1696. }
  1697. BOOL
  1698. NeEnumResourceNamesW (
  1699. IN HANDLE Handle,
  1700. IN PCWSTR Type,
  1701. IN ENUMRESNAMEPROCW EnumFunc,
  1702. IN LONG_PTR lParam
  1703. )
  1704. {
  1705. BOOL b;
  1706. PCSTR AnsiType;
  1707. AnsiType = pConvertUnicodeResourceId (Type);
  1708. b = pNeEnumResourceNamesEx (
  1709. Handle,
  1710. AnsiType,
  1711. (ENUMRESNAMEPROCEXA) EnumFunc,
  1712. lParam,
  1713. FALSE, // no ex functionality
  1714. TRUE // UNICODE enum proc
  1715. );
  1716. PushError();
  1717. DestroyAnsiResourceId (AnsiType);
  1718. PopError();
  1719. return b;
  1720. }
  1721. BOOL
  1722. pEnumTypeForResSearchProcA (
  1723. IN HANDLE Handle,
  1724. IN PCSTR Type,
  1725. IN PCSTR Name,
  1726. IN LPARAM lParam,
  1727. IN PNE_RES_TYPEINFO TypeInfo,
  1728. IN PNE_RES_NAMEINFO NameInfo
  1729. )
  1730. {
  1731. PNAMESEARCHDATAA Data;
  1732. Data = (PNAMESEARCHDATAA) lParam;
  1733. //
  1734. // Compare name
  1735. //
  1736. if (HIWORD (Data->NameToFind) == 0) {
  1737. if (Name != Data->NameToFind) {
  1738. return TRUE;
  1739. }
  1740. } else {
  1741. if (HIWORD (Name) == 0) {
  1742. return TRUE;
  1743. }
  1744. if (!StringIMatchA (Name, Data->NameToFind)) {
  1745. return TRUE;
  1746. }
  1747. }
  1748. //
  1749. // Name found
  1750. //
  1751. Data->OutboundTypeInfo = TypeInfo;
  1752. Data->OutboundNameInfo = NameInfo;
  1753. Data->Found = TRUE;
  1754. return FALSE;
  1755. }
  1756. PBYTE
  1757. NeFindResourceExA (
  1758. IN HANDLE Handle,
  1759. IN PCSTR Type,
  1760. IN PCSTR Name
  1761. )
  1762. {
  1763. PNE_HANDLE NeHandle;
  1764. NAMESEARCHDATAA Data;
  1765. DWORD Offset;
  1766. DWORD Length;
  1767. PNE_RES_NAMEINFO NameInfo;
  1768. PBYTE ReturnData;
  1769. Type = pDecodeIdReferenceInString (Type);
  1770. Name = pDecodeIdReferenceInString (Name);
  1771. ZeroMemory (&Data, sizeof (Data));
  1772. //
  1773. // Make sure resources are loaded
  1774. //
  1775. NeHandle = (PNE_HANDLE) Handle;
  1776. if (!NeHandle || !Type || !Name) {
  1777. SetLastError (ERROR_INVALID_PARAMETER);
  1778. return NULL;
  1779. }
  1780. if (!pNeLoadResourcesFromHandle (NeHandle)) {
  1781. return NULL;
  1782. }
  1783. //
  1784. // Find resource
  1785. //
  1786. Data.NameToFind = Name;
  1787. if (!pNeEnumResourceNamesEx (
  1788. Handle,
  1789. Type,
  1790. pEnumTypeForResSearchProcA,
  1791. (LONG_PTR) &Data,
  1792. TRUE,
  1793. FALSE
  1794. )) {
  1795. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1796. return NULL;
  1797. }
  1798. if (!Data.Found) {
  1799. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1800. return NULL;
  1801. }
  1802. NameInfo = Data.OutboundNameInfo;
  1803. Offset = (DWORD) NameInfo->Offset << (DWORD) NeHandle->Resources.AlignShift;
  1804. Length = (DWORD) NameInfo->Length << (DWORD) NeHandle->Resources.AlignShift;
  1805. ReturnData = PmGetMemory (NeHandle->ResourcePool, Length);
  1806. if (!ReturnData) {
  1807. return NULL;
  1808. }
  1809. SetFilePointer (NeHandle->File, Offset, NULL, FILE_BEGIN);
  1810. if (!BfReadFile (NeHandle->File, ReturnData, Length)) {
  1811. PushError();
  1812. MemFree (g_hHeap, 0, ReturnData);
  1813. PopError();
  1814. return NULL;
  1815. }
  1816. return ReturnData;
  1817. }
  1818. PBYTE
  1819. NeFindResourceExW (
  1820. IN HANDLE Handle,
  1821. IN PCWSTR Type,
  1822. IN PCWSTR Name
  1823. )
  1824. {
  1825. PCSTR AnsiType;
  1826. PCSTR AnsiName;
  1827. PBYTE Resource;
  1828. AnsiType = pConvertUnicodeResourceId (Type);
  1829. AnsiName = pConvertUnicodeResourceId (Name);
  1830. Resource = NeFindResourceExA (
  1831. Handle,
  1832. AnsiType,
  1833. AnsiName
  1834. );
  1835. PushError();
  1836. DestroyAnsiResourceId (AnsiType);
  1837. DestroyAnsiResourceId (AnsiName);
  1838. PopError();
  1839. return Resource;
  1840. }
  1841. DWORD
  1842. NeSizeofResourceA (
  1843. IN HANDLE Handle,
  1844. IN PCSTR Type,
  1845. IN PCSTR Name
  1846. )
  1847. {
  1848. PNE_HANDLE NeHandle;
  1849. NAMESEARCHDATAA Data;
  1850. DWORD result = 0;
  1851. SetLastError (ERROR_SUCCESS);
  1852. Type = pDecodeIdReferenceInString (Type);
  1853. Name = pDecodeIdReferenceInString (Name);
  1854. ZeroMemory (&Data, sizeof (Data));
  1855. //
  1856. // Make sure resources are loaded
  1857. //
  1858. NeHandle = (PNE_HANDLE) Handle;
  1859. if (!NeHandle || !Type || !Name) {
  1860. SetLastError (ERROR_INVALID_PARAMETER);
  1861. return 0;
  1862. }
  1863. if (!pNeLoadResourcesFromHandle (NeHandle)) {
  1864. return 0;
  1865. }
  1866. //
  1867. // Find resource
  1868. //
  1869. Data.NameToFind = Name;
  1870. if (!pNeEnumResourceNamesEx (
  1871. Handle,
  1872. Type,
  1873. pEnumTypeForResSearchProcA,
  1874. (LONG_PTR) &Data,
  1875. TRUE,
  1876. FALSE
  1877. )) {
  1878. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1879. return 0;
  1880. }
  1881. if (!Data.Found) {
  1882. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1883. return 0;
  1884. }
  1885. result = Data.OutboundNameInfo->Length;
  1886. result = result<<4;
  1887. return result;
  1888. }
  1889. DWORD
  1890. NeSizeofResourceW (
  1891. IN HANDLE Handle,
  1892. IN PCWSTR Type,
  1893. IN PCWSTR Name
  1894. )
  1895. {
  1896. PCSTR AnsiType;
  1897. PCSTR AnsiName;
  1898. DWORD Size;
  1899. AnsiType = pConvertUnicodeResourceId (Type);
  1900. AnsiName = pConvertUnicodeResourceId (Name);
  1901. Size = NeSizeofResourceA (Handle, AnsiType, AnsiName);
  1902. PushError();
  1903. DestroyAnsiResourceId (AnsiType);
  1904. DestroyAnsiResourceId (AnsiName);
  1905. PopError();
  1906. return Size;
  1907. }