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.

1261 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ne.c
  5. Abstract:
  6. New-Executable parsing routines
  7. Author:
  8. Jim Schmidt (jimschm) 04-May-1998
  9. Revision History:
  10. jimschm 23-Sep-1998 Named icon ID bug fix, error path fixes
  11. --*/
  12. #include "pch.h"
  13. #include "migutilp.h"
  14. //
  15. // NE code
  16. //
  17. typedef struct {
  18. HANDLE File;
  19. DWORD HeaderOffset;
  20. NE_INFO_BLOCK Header;
  21. NE_RESOURCES Resources;
  22. BOOL ResourcesLoaded;
  23. POOLHANDLE ResourcePool;
  24. } NE_HANDLE, *PNE_HANDLE;
  25. typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXA)(HMODULE hModule, PCSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
  26. typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXW)(HMODULE hModule, PCWSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
  27. typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXA)(HMODULE hModule, PCSTR lpType,
  28. PSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
  29. typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXW)(HMODULE hModule, PCWSTR lpType,
  30. PWSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
  31. typedef struct {
  32. PCSTR TypeToFind;
  33. PNE_RES_TYPEINFO OutboundTypeInfo;
  34. BOOL Found;
  35. } TYPESEARCHDATAA, *PTYPESEARCHDATAA;
  36. typedef struct {
  37. PCSTR NameToFind;
  38. PNE_RES_TYPEINFO OutboundTypeInfo;
  39. PNE_RES_NAMEINFO OutboundNameInfo;
  40. BOOL Found;
  41. } NAMESEARCHDATAA, *PNAMESEARCHDATAA;
  42. BOOL
  43. LoadNeHeader (
  44. IN HANDLE File,
  45. OUT PNE_INFO_BLOCK Header
  46. )
  47. {
  48. DOS_HEADER dh;
  49. LONG rc = ERROR_BAD_FORMAT;
  50. BOOL b = FALSE;
  51. __try {
  52. SetFilePointer (File, 0, NULL, FILE_BEGIN);
  53. if (!ReadBinaryBlock (File, &dh, sizeof (DOS_HEADER))) {
  54. __leave;
  55. }
  56. if (dh.e_magic != ('M' + 'Z' * 256)) {
  57. __leave;
  58. }
  59. SetFilePointer (File, dh.e_lfanew, NULL, FILE_BEGIN);
  60. if (!ReadBinaryBlock (File, Header, sizeof (NE_INFO_BLOCK))) {
  61. __leave;
  62. }
  63. if (Header->Signature != ('N' + 'E' * 256) &&
  64. Header->Signature != ('L' + 'E' * 256)
  65. ) {
  66. if (Header->Signature == ('P' + 'E' * 256)) {
  67. rc = ERROR_BAD_EXE_FORMAT;
  68. } else {
  69. rc = ERROR_INVALID_EXE_SIGNATURE;
  70. }
  71. DEBUGMSG ((DBG_NAUSEA, "Header signature is %c%c", Header->Signature & 0xff, Header->Signature >> 8));
  72. __leave;
  73. }
  74. SetFilePointer (File, (DWORD) dh.e_lfanew, NULL, FILE_BEGIN);
  75. b = TRUE;
  76. }
  77. __finally {
  78. if (!b) {
  79. SetLastError (rc);
  80. }
  81. }
  82. return b;
  83. }
  84. DWORD
  85. pComputeSizeOfTypeInfo (
  86. IN PNE_RES_TYPEINFO TypeInfo
  87. )
  88. {
  89. return sizeof (NE_RES_TYPEINFO) + TypeInfo->ResourceCount * sizeof (NE_RES_NAMEINFO);
  90. }
  91. PNE_RES_TYPEINFO
  92. pReadNextTypeInfoStruct (
  93. IN HANDLE File,
  94. IN POOLHANDLE Pool
  95. )
  96. {
  97. WORD Type;
  98. WORD ResCount;
  99. NE_RES_TYPEINFO TypeInfo;
  100. PNE_RES_TYPEINFO ReturnInfo = NULL;
  101. DWORD Size;
  102. if (!ReadBinaryBlock (File, &Type, sizeof (WORD))) {
  103. return NULL;
  104. }
  105. if (!Type) {
  106. return NULL;
  107. }
  108. if (!ReadBinaryBlock (File, &ResCount, sizeof (WORD))) {
  109. return NULL;
  110. }
  111. TypeInfo.TypeId = Type;
  112. TypeInfo.ResourceCount = ResCount;
  113. if (!ReadBinaryBlock (File, &TypeInfo.Reserved, sizeof (DWORD))) {
  114. return NULL;
  115. }
  116. Size = sizeof (NE_RES_NAMEINFO) * ResCount;
  117. ReturnInfo = (PNE_RES_TYPEINFO) PoolMemGetMemory (Pool, Size + sizeof (TypeInfo));
  118. if (!ReturnInfo) {
  119. return NULL;
  120. }
  121. CopyMemory (ReturnInfo, &TypeInfo, sizeof (TypeInfo));
  122. if (!ReadBinaryBlock (File, (PBYTE) ReturnInfo + sizeof (TypeInfo), Size)) {
  123. return NULL;
  124. }
  125. return ReturnInfo;
  126. }
  127. BOOL
  128. pReadTypeInfoArray (
  129. IN HANDLE File,
  130. IN OUT PGROWLIST TypeInfoList
  131. )
  132. {
  133. PNE_RES_TYPEINFO TypeInfo;
  134. DWORD Size;
  135. POOLHANDLE TempPool;
  136. BOOL b = FALSE;
  137. TempPool = PoolMemInitPool();
  138. if (!TempPool) {
  139. return FALSE;
  140. }
  141. __try {
  142. TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
  143. while (TypeInfo) {
  144. Size = pComputeSizeOfTypeInfo (TypeInfo);
  145. if (!GrowListAppend (TypeInfoList, (PBYTE) TypeInfo, Size)) {
  146. __leave;
  147. }
  148. TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
  149. }
  150. b = TRUE;
  151. }
  152. __finally {
  153. PoolMemDestroyPool (TempPool);
  154. }
  155. return b;
  156. }
  157. BOOL
  158. pReadStringArrayA (
  159. IN HANDLE File,
  160. IN OUT PGROWLIST GrowList
  161. )
  162. {
  163. BYTE Size;
  164. CHAR Name[256];
  165. if (!ReadBinaryBlock (File, &Size, sizeof (BYTE))) {
  166. return FALSE;
  167. }
  168. while (Size) {
  169. if (!ReadBinaryBlock (File, Name, (DWORD) Size)) {
  170. return FALSE;
  171. }
  172. Name[Size] = 0;
  173. GrowListAppendString (GrowList, Name);
  174. if (!ReadBinaryBlock (File, &Size, sizeof (BYTE))) {
  175. return FALSE;
  176. }
  177. }
  178. return TRUE;
  179. }
  180. BOOL
  181. LoadNeResources (
  182. IN HANDLE File,
  183. OUT PNE_RESOURCES Resources
  184. )
  185. {
  186. NE_INFO_BLOCK Header;
  187. ZeroMemory (Resources, sizeof (NE_RESOURCES));
  188. if (!LoadNeHeader (File, &Header)) {
  189. return FALSE;
  190. }
  191. //
  192. // Read in NE_RESOURCES struct
  193. //
  194. SetFilePointer (File, (DWORD) Header.OffsetToResourceTable, NULL, FILE_CURRENT);
  195. if (!ReadBinaryBlock (File, &Resources->AlignShift, sizeof (WORD))) {
  196. return FALSE;
  197. }
  198. // Array of NE_RES_TYPEINFO structs
  199. if (!pReadTypeInfoArray (File, &Resources->TypeInfoArray)) {
  200. return FALSE;
  201. }
  202. // Resource names
  203. if (!pReadStringArrayA (File, &Resources->ResourceNames)) {
  204. return FALSE;
  205. }
  206. return TRUE;
  207. }
  208. VOID
  209. FreeNeResources (
  210. PNE_RESOURCES Resources
  211. )
  212. {
  213. FreeGrowList (&Resources->TypeInfoArray);
  214. FreeGrowList (&Resources->ResourceNames);
  215. ZeroMemory (Resources, sizeof (NE_RESOURCES));
  216. }
  217. BOOL
  218. LoadNeIcon (
  219. HANDLE File,
  220. INT IconIndex
  221. )
  222. {
  223. NE_RESOURCES Resources;
  224. INT Count;
  225. INT i;
  226. PNE_RES_TYPEINFO TypeInfo = NULL;
  227. BOOL b = FALSE;
  228. DWORD Offset;
  229. WORD w;
  230. PNE_RES_NAMEINFO NameInfo;
  231. DWORD Length;
  232. PBYTE Data;
  233. if (!LoadNeResources (File, &Resources)) {
  234. return FALSE;
  235. }
  236. __try {
  237. //
  238. // Search resources for RT_GROUPICON
  239. //
  240. Count = GrowListGetSize (&Resources.TypeInfoArray);
  241. for (i = 0 ; i < Count ; i++) {
  242. TypeInfo = (PNE_RES_TYPEINFO) GrowListGetItem (&Resources.TypeInfoArray, i);
  243. if (TypeInfo->TypeId == (WORD) RT_GROUP_ICON) {
  244. break;
  245. }
  246. }
  247. if (i == Count) {
  248. __leave;
  249. }
  250. //
  251. // Identify which group icon
  252. //
  253. NameInfo = TypeInfo->NameInfo;
  254. for (w = 0 ; w < TypeInfo->ResourceCount ; w++) {
  255. if (IconIndex > 0) {
  256. IconIndex--;
  257. } else if (!IconIndex) {
  258. break;
  259. } else if (-IconIndex == (INT) NameInfo->Id) {
  260. break;
  261. }
  262. NameInfo++;
  263. }
  264. if (w == TypeInfo->ResourceCount) {
  265. __leave;
  266. }
  267. //
  268. // Load the group icon resource
  269. //
  270. Offset = (DWORD) NameInfo->Offset << (DWORD) Resources.AlignShift;
  271. Length = (DWORD) NameInfo->Length << (DWORD) Resources.AlignShift;
  272. Data = MemAlloc (g_hHeap, 0, Length);
  273. if (!Data) {
  274. __leave;
  275. }
  276. SetFilePointer (File, Offset, NULL, FILE_BEGIN);
  277. ReadBinaryBlock (File, Data, Length);
  278. MemFree (g_hHeap, 0, Data);
  279. b = TRUE;
  280. }
  281. __finally {
  282. FreeNeResources (&Resources);
  283. }
  284. return b;
  285. }
  286. BOOL
  287. LoadNeIconFromFileA (
  288. PCSTR FileName,
  289. INT IconIndex
  290. )
  291. {
  292. HANDLE File;
  293. BOOL b;
  294. File = OpenNeFileA (FileName);
  295. if (!File) {
  296. return FALSE;
  297. }
  298. b = LoadNeIcon (File, IconIndex);
  299. CloseNeFile (File);
  300. return b;
  301. }
  302. HANDLE
  303. OpenNeFileA (
  304. PCSTR FileName
  305. )
  306. {
  307. PNE_HANDLE NeHandle;
  308. BOOL b = FALSE;
  309. NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
  310. __try {
  311. NeHandle->ResourcePool = PoolMemInitPool();
  312. if (!NeHandle->ResourcePool) {
  313. __leave;
  314. }
  315. NeHandle->File = CreateFileA (
  316. FileName,
  317. GENERIC_READ,
  318. FILE_SHARE_READ,
  319. NULL,
  320. OPEN_EXISTING,
  321. FILE_ATTRIBUTE_NORMAL,
  322. NULL
  323. );
  324. if (NeHandle->File == INVALID_HANDLE_VALUE) {
  325. __leave;
  326. }
  327. if (!LoadNeHeader (NeHandle->File, &NeHandle->Header)) {
  328. __leave;
  329. }
  330. NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
  331. b = TRUE;
  332. }
  333. __finally {
  334. if (!b) {
  335. PushError();
  336. if (NeHandle->ResourcePool) {
  337. PoolMemDestroyPool (NeHandle->ResourcePool);
  338. }
  339. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  340. CloseHandle (NeHandle->File);
  341. }
  342. MemFree (g_hHeap, 0, NeHandle);
  343. NeHandle = NULL;
  344. PopError();
  345. }
  346. }
  347. return (HANDLE) NeHandle;
  348. }
  349. HANDLE
  350. OpenNeFileW (
  351. PCWSTR FileName
  352. )
  353. {
  354. PNE_HANDLE NeHandle;
  355. BOOL b = FALSE;
  356. NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
  357. __try {
  358. NeHandle->ResourcePool = PoolMemInitPool();
  359. if (!NeHandle->ResourcePool) {
  360. __leave;
  361. }
  362. NeHandle->File = CreateFileW (
  363. FileName,
  364. GENERIC_READ,
  365. FILE_SHARE_READ,
  366. NULL,
  367. OPEN_EXISTING,
  368. FILE_ATTRIBUTE_NORMAL,
  369. NULL
  370. );
  371. if (NeHandle->File == INVALID_HANDLE_VALUE) {
  372. __leave;
  373. }
  374. if (!LoadNeHeader (NeHandle->File, &NeHandle->Header)) {
  375. __leave;
  376. }
  377. NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
  378. b = TRUE;
  379. }
  380. __finally {
  381. if (!b) {
  382. PushError();
  383. if (NeHandle->ResourcePool) {
  384. PoolMemDestroyPool (NeHandle->ResourcePool);
  385. }
  386. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  387. CloseHandle (NeHandle->File);
  388. }
  389. MemFree (g_hHeap, 0, NeHandle);
  390. NeHandle = NULL;
  391. PopError();
  392. }
  393. }
  394. return (HANDLE) NeHandle;
  395. }
  396. VOID
  397. CloseNeFile (
  398. HANDLE Handle
  399. )
  400. {
  401. PNE_HANDLE NeHandle;
  402. NeHandle = (PNE_HANDLE) Handle;
  403. if (!NeHandle) {
  404. return;
  405. }
  406. if (NeHandle->File != INVALID_HANDLE_VALUE) {
  407. CloseHandle (NeHandle->File);
  408. }
  409. if (NeHandle->ResourcesLoaded) {
  410. FreeNeResources (&NeHandle->Resources);
  411. }
  412. PoolMemDestroyPool (NeHandle->ResourcePool);
  413. MemFree (g_hHeap, 0, NeHandle);
  414. }
  415. PCSTR
  416. pConvertUnicodeResourceId (
  417. IN PCWSTR ResId
  418. )
  419. {
  420. if (HIWORD (ResId)) {
  421. return ConvertWtoA (ResId);
  422. }
  423. return (PCSTR) ResId;
  424. }
  425. PCSTR
  426. pDecodeIdReferenceInString (
  427. IN PCSTR ResName
  428. )
  429. {
  430. if (HIWORD (ResName) && ResName[0] == '#') {
  431. return (PCSTR) atoi (&ResName[1]);
  432. }
  433. return ResName;
  434. }
  435. BOOL
  436. pLoadNeResourcesFromHandle (
  437. IN PNE_HANDLE NeHandle
  438. )
  439. {
  440. if (NeHandle->ResourcesLoaded) {
  441. return TRUE;
  442. }
  443. if (!LoadNeResources (NeHandle->File, &NeHandle->Resources)) {
  444. return FALSE;
  445. }
  446. NeHandle->ResourcesLoaded = TRUE;
  447. return TRUE;
  448. }
  449. BOOL
  450. pLoadNeResourceName (
  451. OUT PSTR ResName,
  452. IN HANDLE File,
  453. IN DWORD StringOffset
  454. )
  455. {
  456. BYTE ResNameSize;
  457. SetFilePointer (File, StringOffset, NULL, FILE_BEGIN);
  458. if (!ReadBinaryBlock (File, &ResNameSize, 1)) {
  459. return FALSE;
  460. }
  461. ResName[ResNameSize] = 0;
  462. return ReadBinaryBlock (File, ResName, ResNameSize);
  463. }
  464. BOOL
  465. pEnumNeResourceTypesEx (
  466. IN HANDLE Handle,
  467. IN ENUMRESTYPEPROCEXA EnumFunc,
  468. IN LONG lParam,
  469. IN BOOL ExFunctionality,
  470. IN BOOL UnicodeProc
  471. )
  472. {
  473. PNE_HANDLE NeHandle;
  474. PNE_RES_TYPEINFO TypeInfo;
  475. INT Count;
  476. INT i;
  477. DWORD StringOffset;
  478. CHAR ResName[256];
  479. ENUMRESTYPEPROCA EnumFunc2 = (ENUMRESTYPEPROCA) EnumFunc;
  480. ENUMRESTYPEPROCEXW EnumFuncW = (ENUMRESTYPEPROCEXW) EnumFunc;
  481. ENUMRESTYPEPROCW EnumFunc2W = (ENUMRESTYPEPROCW) EnumFunc;
  482. PWSTR UnicodeResName = NULL;
  483. //
  484. // Make sure resources are loaded
  485. //
  486. NeHandle = (PNE_HANDLE) Handle;
  487. if (!NeHandle || !EnumFunc) {
  488. SetLastError (ERROR_INVALID_PARAMETER);
  489. return FALSE;
  490. }
  491. if (!pLoadNeResourcesFromHandle (NeHandle)) {
  492. return FALSE;
  493. }
  494. //
  495. // Enumerate all resource types
  496. //
  497. Count = GrowListGetSize (&NeHandle->Resources.TypeInfoArray);
  498. for (i = 0 ; i < Count ; i++) {
  499. TypeInfo = (PNE_RES_TYPEINFO) GrowListGetItem (&NeHandle->Resources.TypeInfoArray, i);
  500. if (TypeInfo->TypeId & 0x8000) {
  501. if (ExFunctionality) {
  502. if (UnicodeProc) {
  503. if (!EnumFuncW (Handle, (PWSTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
  504. break;
  505. }
  506. } else {
  507. if (!EnumFunc (Handle, (PSTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
  508. break;
  509. }
  510. }
  511. } else {
  512. if (UnicodeProc) {
  513. if (!EnumFunc2W (Handle, (PWSTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
  514. break;
  515. }
  516. } else {
  517. if (!EnumFunc2 (Handle, (PSTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
  518. break;
  519. }
  520. }
  521. }
  522. } else {
  523. //
  524. // TypeInfo->TypeId gives an offset to the resource string name,
  525. // relative to the start of the resource table
  526. //
  527. StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + TypeInfo->TypeId;
  528. pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
  529. if (UnicodeProc) {
  530. UnicodeResName = (PWSTR) ConvertAtoW (ResName);
  531. }
  532. if (ExFunctionality) {
  533. if (UnicodeProc) {
  534. if (!EnumFuncW (Handle, UnicodeResName, lParam, TypeInfo)) {
  535. break;
  536. }
  537. } else {
  538. if (!EnumFunc (Handle, ResName, lParam, TypeInfo)) {
  539. break;
  540. }
  541. }
  542. } else {
  543. if (UnicodeProc) {
  544. if (!EnumFunc2W (Handle, UnicodeResName, lParam)) {
  545. break;
  546. }
  547. } else {
  548. if (!EnumFunc2 (Handle, ResName, lParam)) {
  549. break;
  550. }
  551. }
  552. }
  553. }
  554. }
  555. return TRUE;
  556. }
  557. BOOL
  558. EnumNeResourceTypesA (
  559. IN HANDLE Handle,
  560. IN ENUMRESTYPEPROCA EnumFunc,
  561. IN LONG lParam
  562. )
  563. {
  564. return pEnumNeResourceTypesEx (
  565. Handle,
  566. (ENUMRESTYPEPROCEXA) EnumFunc,
  567. lParam,
  568. FALSE, // no ex functionality
  569. FALSE // ANSI enum proc
  570. );
  571. }
  572. BOOL
  573. EnumNeResourceTypesW (
  574. IN HANDLE Handle,
  575. IN ENUMRESTYPEPROCW EnumFunc,
  576. IN LONG lParam
  577. )
  578. {
  579. return pEnumNeResourceTypesEx (
  580. Handle,
  581. (ENUMRESTYPEPROCEXA) EnumFunc,
  582. lParam,
  583. FALSE, // no ex functionality
  584. TRUE // UNICODE enum proc
  585. );
  586. }
  587. BOOL
  588. pEnumTypeForNameSearchProcA (
  589. IN HANDLE Handle,
  590. IN PCSTR Type,
  591. IN LONG lParam,
  592. IN PNE_RES_TYPEINFO TypeInfo
  593. )
  594. {
  595. PTYPESEARCHDATAA Data;
  596. Data = (PTYPESEARCHDATAA) lParam;
  597. //
  598. // Compare type
  599. //
  600. if (HIWORD (Data->TypeToFind) == 0) {
  601. if (Type != Data->TypeToFind) {
  602. return TRUE;
  603. }
  604. } else {
  605. if (HIWORD (Type) == 0) {
  606. return TRUE;
  607. }
  608. if (!StringIMatchA (Type, Data->TypeToFind)) {
  609. return TRUE;
  610. }
  611. }
  612. //
  613. // Type found
  614. //
  615. Data->OutboundTypeInfo = TypeInfo;
  616. Data->Found = TRUE;
  617. return FALSE;
  618. }
  619. BOOL
  620. pEnumNeResourceNamesEx (
  621. IN HANDLE Handle,
  622. IN PCSTR Type,
  623. IN ENUMRESNAMEPROCEXA EnumFunc,
  624. IN LONG lParam,
  625. IN BOOL ExFunctionality,
  626. IN BOOL UnicodeProc
  627. )
  628. {
  629. PNE_HANDLE NeHandle;
  630. PNE_RES_TYPEINFO TypeInfo;
  631. PNE_RES_NAMEINFO NameInfo;
  632. TYPESEARCHDATAA Data;
  633. WORD w;
  634. DWORD StringOffset;
  635. CHAR ResName[256];
  636. ENUMRESNAMEPROCA EnumFunc2 = (ENUMRESNAMEPROCA) EnumFunc;
  637. ENUMRESNAMEPROCEXW EnumFuncW = (ENUMRESNAMEPROCEXW) EnumFunc;
  638. ENUMRESNAMEPROCW EnumFunc2W = (ENUMRESNAMEPROCW) EnumFunc;
  639. PCWSTR UnicodeType = NULL;
  640. PCWSTR UnicodeResName = NULL;
  641. Type = pDecodeIdReferenceInString (Type);
  642. //
  643. // Make sure resources are loaded
  644. //
  645. NeHandle = (PNE_HANDLE) Handle;
  646. if (!NeHandle || !EnumFunc) {
  647. SetLastError (ERROR_INVALID_PARAMETER);
  648. return FALSE;
  649. }
  650. if (!pLoadNeResourcesFromHandle (NeHandle)) {
  651. return FALSE;
  652. }
  653. //
  654. // Locate type
  655. //
  656. ZeroMemory (&Data, sizeof (Data));
  657. Data.TypeToFind = Type;
  658. if (!pEnumNeResourceTypesEx (
  659. Handle,
  660. pEnumTypeForNameSearchProcA,
  661. (LONG) &Data,
  662. TRUE, // ex functionality
  663. FALSE // ANSI enum proc
  664. )) {
  665. SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
  666. return FALSE;
  667. }
  668. if (!Data.Found) {
  669. SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
  670. return FALSE;
  671. }
  672. TypeInfo = Data.OutboundTypeInfo;
  673. if (UnicodeProc) {
  674. if (HIWORD (Type)) {
  675. UnicodeType = ConvertAtoW (Type);
  676. } else {
  677. UnicodeType = (PCWSTR) Type;
  678. }
  679. }
  680. //
  681. // Enumerate the resource names
  682. //
  683. NameInfo = TypeInfo->NameInfo;
  684. for (w = 0 ; w < TypeInfo->ResourceCount ; w++) {
  685. if (NameInfo->Id & 0x8000) {
  686. if (ExFunctionality) {
  687. if (UnicodeProc) {
  688. if (!EnumFuncW (Handle, UnicodeType, (PWSTR) (NameInfo->Id & 0x7fff), lParam, TypeInfo, NameInfo)) {
  689. break;
  690. }
  691. } else {
  692. if (!EnumFunc (Handle, Type, (PSTR) (NameInfo->Id & 0x7fff), lParam, TypeInfo, NameInfo)) {
  693. break;
  694. }
  695. }
  696. } else {
  697. if (UnicodeProc) {
  698. if (!EnumFunc2W (Handle, UnicodeType, (PWSTR) (NameInfo->Id & 0x7fff), lParam)) {
  699. break;
  700. }
  701. } else {
  702. if (!EnumFunc2 (Handle, Type, (PSTR) (NameInfo->Id & 0x7fff), lParam)) {
  703. break;
  704. }
  705. }
  706. }
  707. } else {
  708. //
  709. // TypeInfo->TypeId gives an offset to the resource string name,
  710. // relative to the start of the resource table
  711. //
  712. StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + NameInfo->Id;
  713. pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
  714. if (UnicodeProc) {
  715. UnicodeResName = ConvertAtoW (ResName);
  716. }
  717. if (ExFunctionality) {
  718. if (UnicodeProc) {
  719. if (!EnumFuncW (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam, TypeInfo, NameInfo)) {
  720. break;
  721. }
  722. } else {
  723. if (!EnumFunc (Handle, Type, ResName, lParam, TypeInfo, NameInfo)) {
  724. break;
  725. }
  726. }
  727. } else {
  728. if (UnicodeProc) {
  729. if (!EnumFunc2W (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam)) {
  730. break;
  731. }
  732. } else {
  733. if (!EnumFunc2 (Handle, Type, ResName, lParam)) {
  734. break;
  735. }
  736. }
  737. }
  738. if (UnicodeProc) {
  739. FreeConvertedStr (UnicodeResName);
  740. }
  741. }
  742. NameInfo++;
  743. }
  744. if (UnicodeProc) {
  745. DestroyUnicodeResourceId (UnicodeType);
  746. }
  747. return TRUE;
  748. }
  749. BOOL
  750. EnumNeResourceNamesA (
  751. IN HANDLE Handle,
  752. IN PCSTR Type,
  753. IN ENUMRESNAMEPROCA EnumFunc,
  754. IN LONG lParam
  755. )
  756. {
  757. return pEnumNeResourceNamesEx (
  758. Handle,
  759. Type,
  760. (ENUMRESNAMEPROCEXA) EnumFunc,
  761. lParam,
  762. FALSE, // no ex functionality
  763. FALSE // ANSI enum proc
  764. );
  765. }
  766. BOOL
  767. EnumNeResourceNamesW (
  768. IN HANDLE Handle,
  769. IN PCWSTR Type,
  770. IN ENUMRESNAMEPROCW EnumFunc,
  771. IN LONG lParam
  772. )
  773. {
  774. BOOL b;
  775. PCSTR AnsiType;
  776. AnsiType = pConvertUnicodeResourceId (Type);
  777. b = pEnumNeResourceNamesEx (
  778. Handle,
  779. AnsiType,
  780. (ENUMRESNAMEPROCEXA) EnumFunc,
  781. lParam,
  782. FALSE, // no ex functionality
  783. TRUE // UNICODE enum proc
  784. );
  785. PushError();
  786. DestroyAnsiResourceId (AnsiType);
  787. PopError();
  788. return b;
  789. }
  790. BOOL
  791. pEnumTypeForResSearchProcA (
  792. IN HANDLE Handle,
  793. IN PCSTR Type,
  794. IN PCSTR Name,
  795. IN LPARAM lParam,
  796. IN PNE_RES_TYPEINFO TypeInfo,
  797. IN PNE_RES_NAMEINFO NameInfo
  798. )
  799. {
  800. PNAMESEARCHDATAA Data;
  801. Data = (PNAMESEARCHDATAA) lParam;
  802. //
  803. // Compare name
  804. //
  805. if (HIWORD (Data->NameToFind) == 0) {
  806. if (Name != Data->NameToFind) {
  807. return TRUE;
  808. }
  809. } else {
  810. if (HIWORD (Name) == 0) {
  811. return TRUE;
  812. }
  813. if (!StringIMatchA (Name, Data->NameToFind)) {
  814. return TRUE;
  815. }
  816. }
  817. //
  818. // Name found
  819. //
  820. Data->OutboundTypeInfo = TypeInfo;
  821. Data->OutboundNameInfo = NameInfo;
  822. Data->Found = TRUE;
  823. return FALSE;
  824. }
  825. PBYTE
  826. FindNeResourceExA (
  827. IN HANDLE Handle,
  828. IN PCSTR Type,
  829. IN PCSTR Name
  830. )
  831. {
  832. PNE_HANDLE NeHandle;
  833. NAMESEARCHDATAA Data;
  834. DWORD Offset;
  835. DWORD Length;
  836. PNE_RES_NAMEINFO NameInfo;
  837. PBYTE ReturnData;
  838. Type = pDecodeIdReferenceInString (Type);
  839. Name = pDecodeIdReferenceInString (Name);
  840. ZeroMemory (&Data, sizeof (Data));
  841. //
  842. // Make sure resources are loaded
  843. //
  844. NeHandle = (PNE_HANDLE) Handle;
  845. if (!NeHandle || !Type || !Name) {
  846. SetLastError (ERROR_INVALID_PARAMETER);
  847. return NULL;
  848. }
  849. if (!pLoadNeResourcesFromHandle (NeHandle)) {
  850. return NULL;
  851. }
  852. //
  853. // Find resource
  854. //
  855. Data.NameToFind = Name;
  856. if (!pEnumNeResourceNamesEx (
  857. Handle,
  858. Type,
  859. pEnumTypeForResSearchProcA,
  860. (LONG) &Data,
  861. TRUE,
  862. FALSE
  863. )) {
  864. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  865. return NULL;
  866. }
  867. if (!Data.Found) {
  868. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  869. return NULL;
  870. }
  871. NameInfo = Data.OutboundNameInfo;
  872. Offset = (DWORD) NameInfo->Offset << (DWORD) NeHandle->Resources.AlignShift;
  873. Length = (DWORD) NameInfo->Length << (DWORD) NeHandle->Resources.AlignShift;
  874. ReturnData = PoolMemGetMemory (NeHandle->ResourcePool, Length);
  875. if (!ReturnData) {
  876. return NULL;
  877. }
  878. SetFilePointer (NeHandle->File, Offset, NULL, FILE_BEGIN);
  879. if (!ReadBinaryBlock (NeHandle->File, ReturnData, Length)) {
  880. PushError();
  881. MemFree (g_hHeap, 0, ReturnData);
  882. PopError();
  883. return NULL;
  884. }
  885. return ReturnData;
  886. }
  887. PBYTE
  888. FindNeResourceExW (
  889. IN HANDLE Handle,
  890. IN PCWSTR Type,
  891. IN PCWSTR Name
  892. )
  893. {
  894. PCSTR AnsiType;
  895. PCSTR AnsiName;
  896. PBYTE Resource;
  897. AnsiType = pConvertUnicodeResourceId (Type);
  898. AnsiName = pConvertUnicodeResourceId (Name);
  899. Resource = FindNeResourceExA (
  900. Handle,
  901. AnsiType,
  902. AnsiName
  903. );
  904. PushError();
  905. DestroyAnsiResourceId (AnsiType);
  906. DestroyAnsiResourceId (AnsiName);
  907. PopError();
  908. return Resource;
  909. }
  910. DWORD
  911. SizeofNeResourceA (
  912. IN HANDLE Handle,
  913. IN PCSTR Type,
  914. IN PCSTR Name
  915. )
  916. {
  917. PNE_HANDLE NeHandle;
  918. NAMESEARCHDATAA Data;
  919. SetLastError (ERROR_SUCCESS);
  920. Type = pDecodeIdReferenceInString (Type);
  921. Name = pDecodeIdReferenceInString (Name);
  922. ZeroMemory (&Data, sizeof (Data));
  923. //
  924. // Make sure resources are loaded
  925. //
  926. NeHandle = (PNE_HANDLE) Handle;
  927. if (!NeHandle || !Type || !Name) {
  928. SetLastError (ERROR_INVALID_PARAMETER);
  929. return 0;
  930. }
  931. if (!pLoadNeResourcesFromHandle (NeHandle)) {
  932. return 0;
  933. }
  934. //
  935. // Find resource
  936. //
  937. if (!pEnumNeResourceNamesEx (
  938. Handle,
  939. Type,
  940. pEnumTypeForResSearchProcA,
  941. (LONG) &Data,
  942. TRUE,
  943. FALSE
  944. )) {
  945. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  946. return 0;
  947. }
  948. if (!Data.Found) {
  949. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  950. return 0;
  951. }
  952. return Data.OutboundNameInfo->Length;
  953. }
  954. DWORD
  955. SizeofNeResourceW (
  956. IN HANDLE Handle,
  957. IN PCWSTR Type,
  958. IN PCWSTR Name
  959. )
  960. {
  961. PCSTR AnsiType;
  962. PCSTR AnsiName;
  963. DWORD Size;
  964. AnsiType = pConvertUnicodeResourceId (Type);
  965. AnsiName = pConvertUnicodeResourceId (Name);
  966. Size = SizeofNeResourceA (Handle, AnsiType, AnsiName);
  967. PushError();
  968. DestroyAnsiResourceId (AnsiType);
  969. DestroyAnsiResourceId (AnsiName);
  970. PopError();
  971. return Size;
  972. }