Leaked source code of windows server 2003
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.

2697 lines
63 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. icons.c
  5. Abstract:
  6. Icon extraction and manipulation routines
  7. Author:
  8. Jim Schmidt (jimschm) 04-May-1998
  9. Revision History:
  10. jimschm 23-Sep-1998 String icon ID bug fixes, error path bug fixes
  11. --*/
  12. #include "pch.h"
  13. #include "migutilp.h"
  14. #define MAX_RESOLUTIONS 32 // 8 sizes times 4 color palettes
  15. #pragma pack(push)
  16. #pragma pack(2)
  17. typedef struct {
  18. BYTE Width; // Width, in pixels, of the image
  19. BYTE Height; // Height, in pixels, of the image
  20. BYTE ColorCount; // Number of colors in image (0 if >=8bpp)
  21. BYTE Reserved; // Reserved ( must be 0)
  22. WORD Planes; // Color Planes
  23. WORD BitCount; // Bits per pixel
  24. DWORD BytesInRes; // How many bytes in this resource?
  25. DWORD ImageOffset; // Where in the file is this image?
  26. } ICONDIRENTRY, *PICONDIRENTRY;
  27. typedef struct {
  28. WORD Reserved; // Reserved (must be 0)
  29. WORD Type; // Resource Type (1 for icons)
  30. WORD Count; // How many images?
  31. ICONDIRENTRY Entries[1]; // An entry for each image (idCount of 'em)
  32. } ICONDIR, *PICONDIR;
  33. typedef struct {
  34. BYTE Width; // Width, in pixels, of the image
  35. BYTE Height; // Height, in pixels, of the image
  36. BYTE ColorCount; // Number of colors in image (0 if >=8bpp)
  37. BYTE Reserved; // Reserved
  38. WORD Planes; // Color Planes
  39. WORD BitCount; // Bits per pixel
  40. DWORD BytesInRes; // how many bytes in this resource?
  41. WORD ID; // the ID
  42. } GRPICONDIRENTRY, *PGRPICONDIRENTRY;
  43. typedef struct {
  44. WORD Reserved; // Reserved (must be 0)
  45. WORD Type; // Resource type (1 for icons)
  46. WORD Count; // How many images?
  47. GRPICONDIRENTRY Entries[1]; // The entries for each image
  48. } GRPICONDIR, *PGRPICONDIR;
  49. typedef struct {
  50. WORD Reserved; // Reserved (must be 0)
  51. WORD Type; // Resource type (1 for icons)
  52. WORD Count; // How many images?
  53. } GRPICONDIRBASE, *PGRPICONDIRBASE;
  54. #pragma pack( pop )
  55. #define PICONIMAGE PBYTE
  56. BOOL
  57. ReadBinaryBlock (
  58. HANDLE File,
  59. PVOID Buffer,
  60. UINT Size
  61. )
  62. {
  63. DWORD BytesRead;
  64. if(File == INVALID_HANDLE_VALUE || !Buffer || !Size){
  65. MYASSERT(File != INVALID_HANDLE_VALUE);
  66. MYASSERT(Buffer);
  67. MYASSERT(Size);
  68. return FALSE;
  69. }
  70. if (!ReadFile (File, Buffer, Size, &BytesRead, NULL)) {
  71. return FALSE;
  72. }
  73. return Size == BytesRead;
  74. }
  75. BOOL
  76. pWriteBinaryBlock (
  77. HANDLE File,
  78. PVOID Buffer,
  79. UINT Size
  80. )
  81. {
  82. DWORD BytesWritten;
  83. if(File == INVALID_HANDLE_VALUE || !Buffer || !Size){
  84. MYASSERT(File != INVALID_HANDLE_VALUE);
  85. MYASSERT(Buffer);
  86. MYASSERT(Size);
  87. return FALSE;
  88. }
  89. if (!WriteFile (File, Buffer, Size, &BytesWritten, NULL)) {
  90. return FALSE;
  91. }
  92. return Size == BytesWritten;
  93. }
  94. UINT
  95. Power (
  96. UINT x,
  97. UINT e
  98. )
  99. {
  100. UINT r;
  101. r = 1;
  102. while (e > 0) {
  103. r = r * x;
  104. e--;
  105. }
  106. return r;
  107. }
  108. UINT
  109. pComputeSizeOfIconImage (
  110. IN PICONIMAGE IconImage
  111. )
  112. {
  113. PBITMAPINFOHEADER Header;
  114. UINT Size;
  115. UINT Bits;
  116. UINT Colors;
  117. UINT BytesInImage;
  118. MYASSERT(IconImage);
  119. Header = (PBITMAPINFOHEADER) IconImage;
  120. Size = Header->biSize;
  121. Bits = Header->biBitCount * Header->biPlanes;
  122. if (Bits > 32) {
  123. Bits = 4;
  124. }
  125. Colors = Power (2, Bits);
  126. if (Bits < 24) {
  127. Size += Colors * sizeof (RGBQUAD);
  128. }
  129. BytesInImage = (Header->biWidth + 7) / 8 * (Header->biHeight / 2);
  130. Size += BytesInImage * Bits; // XOR mask
  131. //
  132. // The following computation is very strange, but it was added based on
  133. // test comparisons.
  134. //
  135. if (Header->biWidth == 32) {
  136. Size += BytesInImage; // AND mask
  137. } else {
  138. Size += BytesInImage + Header->biHeight; // AND mask plus who knows what
  139. }
  140. MYASSERT (Size);
  141. return Size;
  142. }
  143. BOOL
  144. pAddIconImagesToGrowBuffer (
  145. IN OUT PGROWBUFFER Buffer,
  146. IN HANDLE File,
  147. IN PICONDIRENTRY IconDirEntryBase,
  148. IN WORD Count,
  149. IN DWORD Pos,
  150. IN DWORD Size
  151. )
  152. {
  153. WORD w;
  154. PICONDIRENTRY IconDirEntry;
  155. PBYTE Dest;
  156. DWORD Offset;
  157. MYASSERT(Buffer);
  158. MYASSERT(File != INVALID_HANDLE_VALUE);
  159. MYASSERT(IconDirEntryBase);
  160. for (w = 0 ; w < Count ; w++) {
  161. IconDirEntry = &IconDirEntryBase[w];
  162. MYASSERT(File);
  163. Offset = IconDirEntry->ImageOffset & 0x0fffffff;
  164. if (Offset < Pos || Offset >= Size) {
  165. return FALSE;
  166. }
  167. SetFilePointer (File, Offset, NULL, FILE_BEGIN);
  168. Dest = GrowBuffer (Buffer, IconDirEntry->BytesInRes);
  169. if (!Dest) {
  170. return FALSE;
  171. }
  172. if (!ReadBinaryBlock (File, Dest, IconDirEntry->BytesInRes)) {
  173. return FALSE;
  174. }
  175. if (IconDirEntry->BytesInRes != pComputeSizeOfIconImage (Dest)) {
  176. return FALSE;
  177. }
  178. }
  179. return TRUE;
  180. }
  181. BOOL
  182. pGetIconImageArrayFromIcoFileExW (
  183. IN PCWSTR ModuleContainingIcon,
  184. IN OUT PGROWBUFFER Buffer,
  185. IN HANDLE File
  186. )
  187. {
  188. BOOL b = FALSE;
  189. ICONDIR IconDir;
  190. PICONDIRENTRY IconDirEntryBase = NULL;
  191. DWORD Size;
  192. DWORD Pos;
  193. UINT IconDirEntrySize;
  194. MYASSERT(ModuleContainingIcon);
  195. MYASSERT(Buffer);
  196. MYASSERT(File != INVALID_HANDLE_VALUE);
  197. Size = GetFileSize (File, NULL);
  198. SetFilePointer (File, 0, NULL, FILE_BEGIN);
  199. Buffer->End = 0;
  200. __try {
  201. if (!ReadBinaryBlock (File, &IconDir, sizeof (WORD) * 3)) {
  202. __leave;
  203. }
  204. IconDirEntrySize = (UINT) IconDir.Count * sizeof (ICONDIRENTRY);
  205. if (IconDirEntrySize > (UINT) Size) {
  206. __leave;
  207. }
  208. IconDirEntryBase = (PICONDIRENTRY) MemAlloc (g_hHeap, 0, IconDirEntrySize);
  209. if (!IconDirEntryBase) {
  210. MYASSERT(IconDirEntryBase);
  211. __leave;
  212. }
  213. if (!ReadBinaryBlock (File, IconDirEntryBase, IconDirEntrySize)) {
  214. __leave;
  215. }
  216. Pos = SetFilePointer (File, 0, NULL, FILE_CURRENT);
  217. if (!pAddIconImagesToGrowBuffer (Buffer, File, IconDirEntryBase, IconDir.Count, Pos, Size)) {
  218. DEBUGMSG ((DBG_WARNING, "Icon file %ls has a bogus offset", ModuleContainingIcon));
  219. __leave;
  220. }
  221. b = TRUE;
  222. }
  223. __finally {
  224. if (IconDirEntryBase) {
  225. MemFree (g_hHeap, 0, IconDirEntryBase);
  226. }
  227. }
  228. return b;
  229. }
  230. BOOL
  231. pGetIconImageArrayFromIcoFileExA (
  232. IN PCSTR ModuleContainingIcon,
  233. IN OUT PGROWBUFFER Buffer,
  234. IN HANDLE File
  235. )
  236. {
  237. PCWSTR UnicodeFileName;
  238. BOOL b;
  239. MYASSERT(ModuleContainingIcon);
  240. MYASSERT(Buffer);
  241. MYASSERT(File != INVALID_HANDLE_VALUE);
  242. UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
  243. if (!UnicodeFileName) {
  244. MYASSERT(UnicodeFileName);
  245. return FALSE;
  246. }
  247. b = pGetIconImageArrayFromIcoFileExW (UnicodeFileName, Buffer, File);
  248. PushError();
  249. FreeConvertedStr (UnicodeFileName);
  250. PopError();
  251. return b;
  252. }
  253. BOOL
  254. pGetIconImageArrayFromIcoFileW (
  255. IN PCWSTR ModuleContainingIcon,
  256. IN OUT PGROWBUFFER Buffer
  257. )
  258. {
  259. HANDLE File;
  260. BOOL b = FALSE;
  261. MYASSERT(ModuleContainingIcon);
  262. MYASSERT(Buffer);
  263. File = CreateFileW (ModuleContainingIcon, GENERIC_READ, 0, NULL,
  264. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  265. if (File == INVALID_HANDLE_VALUE) {
  266. DEBUGMSG ((DBG_WARNING, "%ls could not be opened", ModuleContainingIcon));
  267. return FALSE;
  268. }
  269. __try {
  270. b = pGetIconImageArrayFromIcoFileExW (ModuleContainingIcon, Buffer, File);
  271. }
  272. __finally {
  273. CloseHandle (File);
  274. }
  275. return b;
  276. }
  277. BOOL
  278. pGetIconImageArrayFromIcoFileA (
  279. IN PCSTR ModuleContainingIcon,
  280. IN OUT PGROWBUFFER Buffer
  281. )
  282. {
  283. PCWSTR UnicodeFileName;
  284. BOOL b;
  285. MYASSERT(ModuleContainingIcon);
  286. MYASSERT(Buffer);
  287. UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
  288. if (!UnicodeFileName) {
  289. MYASSERT(UnicodeFileName);
  290. return FALSE;
  291. }
  292. b = pGetIconImageArrayFromIcoFileW (UnicodeFileName, Buffer);
  293. PushError();
  294. FreeConvertedStr (UnicodeFileName);
  295. PopError();
  296. return b;
  297. }
  298. BOOL
  299. pGetIconImageArrayFromBinaryExW (
  300. IN PCWSTR ModuleContainingIcon,
  301. IN PCWSTR GroupIconId,
  302. IN OUT PGROWBUFFER Buffer,
  303. IN HANDLE Library,
  304. IN HANDLE Library16
  305. )
  306. {
  307. HRSRC ResourceHandle;
  308. HGLOBAL ResourceBlock;
  309. PBYTE ResourceData;
  310. DWORD ResourceSize;
  311. PBYTE Dest;
  312. BOOL b = FALSE;
  313. PGRPICONDIR GroupIconDir;
  314. WORD w;
  315. MYASSERT(ModuleContainingIcon);
  316. MYASSERT(Buffer);
  317. if (!GroupIconId) {
  318. return FALSE;
  319. }
  320. __try {
  321. Buffer->End = 0;
  322. if (Library) {
  323. //
  324. // Get icon from PE file
  325. //
  326. ResourceHandle = FindResourceW (Library, GroupIconId, (PCWSTR) RT_GROUP_ICON);
  327. if (!ResourceHandle) {
  328. __leave;
  329. }
  330. ResourceBlock = LoadResource (Library, ResourceHandle);
  331. if (!ResourceBlock) {
  332. __leave;
  333. }
  334. GroupIconDir = (PGRPICONDIR) LockResource (ResourceBlock);
  335. if (!GroupIconDir) {
  336. __leave;
  337. }
  338. if (GroupIconDir->Type != 1) {
  339. DEBUGMSGW_IF ((
  340. (UINT_PTR) GroupIconId < 0x10000,
  341. DBG_ERROR,
  342. "icon type for resource %u is not 1 in %s",
  343. GroupIconId,
  344. ModuleContainingIcon
  345. ));
  346. DEBUGMSGW_IF ((
  347. (UINT_PTR) GroupIconId >= 0x10000,
  348. DBG_ERROR,
  349. "icon type for resource %s is not 1 in %s",
  350. GroupIconId,
  351. ModuleContainingIcon
  352. ));
  353. __leave;
  354. }
  355. if (GroupIconDir->Count > MAX_RESOLUTIONS) {
  356. DEBUGMSGW ((DBG_ERROR, "%u resolutions found in %s", GroupIconDir->Count, ModuleContainingIcon));
  357. __leave;
  358. }
  359. //
  360. // Add the ICONIMAGE array to the grow buffer
  361. //
  362. for (w = 0 ; w < GroupIconDir->Count ; w++) {
  363. ResourceHandle = FindResourceW (
  364. Library,
  365. (PCWSTR) (GroupIconDir->Entries[w].ID),
  366. (PCWSTR) RT_ICON
  367. );
  368. if (ResourceHandle) {
  369. ResourceBlock = LoadResource (Library, ResourceHandle);
  370. if (!ResourceBlock) {
  371. continue;
  372. }
  373. ResourceData = (PBYTE) LockResource (ResourceBlock);
  374. if (!ResourceData) {
  375. continue;
  376. }
  377. ResourceSize = pComputeSizeOfIconImage ((PICONIMAGE) ResourceData);
  378. if (!ResourceSize) {
  379. DEBUGMSG ((DBG_WARNING, "Zero-length icon in %s", ModuleContainingIcon));
  380. continue;
  381. }
  382. if (ResourceSize > 0x10000) {
  383. // too big for an icon
  384. __leave;
  385. }
  386. Dest = GrowBuffer (Buffer, ResourceSize);
  387. if (!Dest) {
  388. __leave;
  389. }
  390. CopyMemory (Dest, ResourceData, ResourceSize);
  391. }
  392. ELSE_DEBUGMSG ((DBG_WARNING, "Indexed icon could not be loaded from resource"));
  393. }
  394. }
  395. else if (Library16) {
  396. //
  397. // Get icon from NE file
  398. //
  399. GroupIconDir = (PGRPICONDIR) FindNeResourceExW (Library16, (PCWSTR) RT_GROUP_ICON, GroupIconId);
  400. if (!GroupIconDir) {
  401. DEBUGMSG ((DBG_WHOOPS, "NE group icon %u not found", GroupIconId));
  402. __leave;
  403. }
  404. DEBUGMSG_IF ((GroupIconDir->Count > MAX_RESOLUTIONS, DBG_WHOOPS, "%u resolutions found in %hs", GroupIconDir->Count, ModuleContainingIcon));
  405. //
  406. // Add the ICONIMAGE array to the grow buffer
  407. //
  408. for (w = 0 ; w < GroupIconDir->Count ; w++) {
  409. ResourceData = FindNeResourceExA (
  410. Library16,
  411. (PCSTR) RT_ICON,
  412. (PCSTR) GroupIconDir->Entries[w].ID
  413. );
  414. if (!ResourceData) {
  415. DEBUGMSG ((DBG_WHOOPS, "NE Icon ID %u not found", GroupIconDir->Entries[w].ID));
  416. __leave;
  417. }
  418. ResourceSize = pComputeSizeOfIconImage ((PICONIMAGE) ResourceData);
  419. if (!ResourceSize) {
  420. DEBUGMSG ((DBG_WARNING, "Zero-length icon in %s", ModuleContainingIcon));
  421. continue;
  422. }
  423. if (ResourceSize > 0x10000) {
  424. // too big for an icon
  425. __leave;
  426. }
  427. Dest = GrowBuffer (Buffer, ResourceSize);
  428. if (!Dest) {
  429. __leave;
  430. }
  431. CopyMemory (Dest, ResourceData, ResourceSize);
  432. }
  433. }
  434. b = TRUE;
  435. }
  436. __finally {
  437. // empty
  438. }
  439. return b;
  440. }
  441. BOOL
  442. pGenerateUnicodeArgs (
  443. IN PCSTR ModuleContainingIcon, OPTIONAL
  444. IN PCSTR GroupIconId, OPTIONAL
  445. OUT PCWSTR *UnicodeFileName, OPTIONAL
  446. OUT PCWSTR *UnicodeGroupIconId OPTIONAL
  447. )
  448. {
  449. if (UnicodeFileName) {
  450. if (ModuleContainingIcon) {
  451. *UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
  452. if (!(*UnicodeFileName)) {
  453. return FALSE;
  454. }
  455. } else {
  456. *UnicodeFileName = NULL;
  457. }
  458. }
  459. if (UnicodeGroupIconId) {
  460. if (GroupIconId) {
  461. if ((UINT_PTR) GroupIconId > 0xffff) {
  462. *UnicodeGroupIconId = ConvertAtoW (GroupIconId);
  463. if (!(*UnicodeGroupIconId)) {
  464. if (UnicodeFileName && *UnicodeFileName) {
  465. FreeConvertedStr (*UnicodeFileName);
  466. }
  467. return FALSE;
  468. }
  469. } else {
  470. *UnicodeGroupIconId = (PCWSTR) GroupIconId;
  471. }
  472. } else {
  473. *UnicodeGroupIconId = NULL;
  474. }
  475. }
  476. return TRUE;
  477. }
  478. VOID
  479. DestroyAnsiResourceId (
  480. IN PCSTR AnsiId
  481. )
  482. {
  483. if (HIWORD (AnsiId)) {
  484. FreeConvertedStr (AnsiId);
  485. }
  486. }
  487. VOID
  488. DestroyUnicodeResourceId (
  489. IN PCWSTR UnicodeId
  490. )
  491. {
  492. if (HIWORD (UnicodeId)) {
  493. FreeConvertedStr (UnicodeId);
  494. }
  495. }
  496. BOOL
  497. pGetIconImageArrayFromBinaryExA (
  498. IN PCSTR ModuleContainingIcon,
  499. IN PCSTR GroupIconId,
  500. IN OUT PGROWBUFFER Buffer,
  501. IN HANDLE Library,
  502. IN HANDLE Library16
  503. )
  504. {
  505. PCWSTR UnicodeFileName;
  506. PCWSTR UnicodeGroupIconId;
  507. BOOL b;
  508. MYASSERT(ModuleContainingIcon);
  509. MYASSERT(Buffer);
  510. if (!pGenerateUnicodeArgs (
  511. ModuleContainingIcon,
  512. GroupIconId,
  513. &UnicodeFileName,
  514. &UnicodeGroupIconId
  515. )) {
  516. return FALSE;
  517. }
  518. b = pGetIconImageArrayFromBinaryExW (UnicodeFileName, UnicodeGroupIconId, Buffer, Library, Library16);
  519. PushError();
  520. FreeConvertedStr (UnicodeFileName);
  521. DestroyUnicodeResourceId (UnicodeGroupIconId);
  522. PopError();
  523. return b;
  524. }
  525. BOOL
  526. pGetIconImageArrayFromBinaryW (
  527. IN PCWSTR ModuleContainingIcon,
  528. IN PCWSTR GroupIconId,
  529. IN OUT PGROWBUFFER Buffer
  530. )
  531. {
  532. HANDLE Library;
  533. HANDLE Library16 = NULL;
  534. BOOL b = FALSE;
  535. MYASSERT(ModuleContainingIcon);
  536. MYASSERT(Buffer);
  537. Library = LoadLibraryExW (ModuleContainingIcon, NULL, LOAD_LIBRARY_AS_DATAFILE);
  538. __try {
  539. if (!Library) {
  540. Library16 = OpenNeFileW (ModuleContainingIcon);
  541. if (!Library16) {
  542. __leave;
  543. }
  544. }
  545. b = pGetIconImageArrayFromBinaryExW (ModuleContainingIcon, GroupIconId, Buffer, Library, Library16);
  546. }
  547. __finally {
  548. if (Library) {
  549. FreeLibrary (Library);
  550. }
  551. if (Library16) {
  552. CloseNeFile (Library16);
  553. }
  554. }
  555. return b;
  556. }
  557. BOOL
  558. pGetIconImageArrayFromBinaryA (
  559. IN PCSTR ModuleContainingIcon,
  560. IN PCSTR GroupIconId,
  561. IN OUT PGROWBUFFER Buffer
  562. )
  563. {
  564. HANDLE Library;
  565. HANDLE Library16 = NULL;
  566. BOOL b = FALSE;
  567. MYASSERT(ModuleContainingIcon);
  568. MYASSERT(Buffer);
  569. Library = LoadLibraryExA (ModuleContainingIcon, NULL, LOAD_LIBRARY_AS_DATAFILE);
  570. __try {
  571. if (!Library) {
  572. Library16 = OpenNeFileA (ModuleContainingIcon);
  573. if (!Library16) {
  574. __leave;
  575. }
  576. }
  577. b = pGetIconImageArrayFromBinaryExA (ModuleContainingIcon, GroupIconId, Buffer, Library, Library16);
  578. }
  579. __finally {
  580. if (Library) {
  581. FreeLibrary (Library);
  582. }
  583. if (Library16) {
  584. CloseNeFile (Library16);
  585. }
  586. }
  587. return b;
  588. }
  589. BOOL
  590. WriteIconImageArrayToIcoFileEx (
  591. IN PGROWBUFFER Buffer,
  592. IN HANDLE File
  593. )
  594. {
  595. WORD w;
  596. BOOL b = FALSE;
  597. PICONIMAGE IconImage, IconImageEnd;
  598. PICONIMAGE p;
  599. INT ImageCount;
  600. ICONDIRENTRY Entry;
  601. PBITMAPINFOHEADER Header;
  602. UINT ColorCount;
  603. DWORD Offset;
  604. if (!Buffer || !Buffer->End) {
  605. MYASSERT(Buffer);
  606. return FALSE;
  607. }
  608. __try {
  609. SetFilePointer (File, 0, NULL, FILE_BEGIN);
  610. //
  611. // Count the images
  612. //
  613. IconImage = (PICONIMAGE) Buffer->Buf;
  614. IconImageEnd = (PICONIMAGE) (Buffer->Buf + Buffer->End);
  615. p = IconImage;
  616. ImageCount = 0;
  617. while (p < IconImageEnd) {
  618. ImageCount++;
  619. p = (PICONIMAGE) ((PBYTE) p + pComputeSizeOfIconImage (p));
  620. }
  621. //
  622. // Write the icon header
  623. //
  624. w = 0; // reserved
  625. if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
  626. __leave;
  627. }
  628. w = 1; // type (1 == icon)
  629. if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
  630. __leave;
  631. }
  632. w = (WORD) ImageCount;
  633. if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
  634. __leave;
  635. }
  636. //
  637. // For each icon image, write the directory entry
  638. //
  639. p = IconImage;
  640. Offset = 0;
  641. while (p < IconImageEnd) {
  642. ZeroMemory (&Entry, sizeof (Entry));
  643. Header = (PBITMAPINFOHEADER) p;
  644. Entry.Width = (BYTE) Header->biWidth;
  645. Entry.Height = (BYTE) Header->biHeight / 2;
  646. ColorCount = Header->biPlanes * Header->biBitCount;
  647. if (ColorCount >= 8) {
  648. Entry.ColorCount = 0;
  649. } else {
  650. Entry.ColorCount = (BYTE) Power (2, ColorCount);
  651. }
  652. Entry.Planes = Header->biPlanes;
  653. Entry.BitCount = Header->biBitCount;
  654. Entry.BytesInRes = pComputeSizeOfIconImage (p);
  655. Entry.ImageOffset = sizeof (WORD) * 3 + sizeof (Entry) * ImageCount + Offset;
  656. if (!pWriteBinaryBlock (File, &Entry, sizeof (Entry))) {
  657. __leave;
  658. }
  659. Offset += Entry.BytesInRes;
  660. p = (PICONIMAGE) ((PBYTE) p + Entry.BytesInRes);
  661. }
  662. //
  663. // Write the image array
  664. //
  665. if (!pWriteBinaryBlock (File, IconImage, Buffer->End)) {
  666. __leave;
  667. }
  668. b = TRUE;
  669. }
  670. __finally {
  671. // empty
  672. }
  673. return b;
  674. }
  675. BOOL
  676. WriteIconImageArrayToIcoFileW (
  677. IN PCWSTR DestinationFile,
  678. IN PGROWBUFFER Buffer
  679. )
  680. {
  681. HANDLE File;
  682. BOOL b = FALSE;
  683. if (!DestinationFile || !Buffer || !Buffer->End) {
  684. MYASSERT(DestinationFile);
  685. MYASSERT(Buffer);
  686. return FALSE;
  687. }
  688. File = CreateFileW (DestinationFile, GENERIC_WRITE, 0, NULL,
  689. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  690. if (File == INVALID_HANDLE_VALUE) {
  691. DEBUGMSG ((DBG_WARNING, "%ls could not be created", DestinationFile));
  692. return FALSE;
  693. }
  694. __try {
  695. b = WriteIconImageArrayToIcoFileEx (Buffer, File);
  696. }
  697. __finally {
  698. CloseHandle (File);
  699. if (!b) {
  700. DeleteFileW (DestinationFile);
  701. }
  702. }
  703. return b;
  704. }
  705. BOOL
  706. WriteIconImageArrayToIcoFileA (
  707. IN PCSTR DestinationFile,
  708. IN PGROWBUFFER Buffer
  709. )
  710. {
  711. HANDLE File;
  712. BOOL b = FALSE;
  713. if (!DestinationFile || !Buffer || !Buffer->End) {
  714. MYASSERT(DestinationFile);
  715. MYASSERT(Buffer);
  716. return FALSE;
  717. }
  718. File = CreateFileA (DestinationFile, GENERIC_WRITE, 0, NULL,
  719. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  720. if (File == INVALID_HANDLE_VALUE) {
  721. DEBUGMSG ((DBG_WARNING, "%hs could not be created", DestinationFile));
  722. return FALSE;
  723. }
  724. __try {
  725. b = WriteIconImageArrayToIcoFileEx (Buffer, File);
  726. }
  727. __finally {
  728. CloseHandle (File);
  729. if (!b) {
  730. DeleteFileA (DestinationFile);
  731. }
  732. }
  733. return b;
  734. }
  735. BOOL
  736. WriteIconImageArrayToPeFileExW (
  737. IN PCWSTR DestinationFile,
  738. IN PGROWBUFFER Buffer,
  739. IN PCWSTR GroupIconId,
  740. IN PWORD NextIconId, OPTIONAL
  741. IN HANDLE UpdateHandle
  742. )
  743. {
  744. BOOL b = FALSE;
  745. GROWBUFFER GroupIcon = GROWBUF_INIT;
  746. PGRPICONDIRBASE IconDir;
  747. PGRPICONDIRENTRY Entry;
  748. PICONIMAGE IconImage, IconImageEnd;
  749. PICONIMAGE p;
  750. PBITMAPINFOHEADER Header;
  751. UINT ColorCount;
  752. if (!DestinationFile || !Buffer) {
  753. MYASSERT(DestinationFile);
  754. MYASSERT(Buffer);
  755. return FALSE;
  756. }
  757. if (!Buffer->End) {
  758. return TRUE;
  759. }
  760. __try {
  761. //
  762. // Make a group icon directory for all icon images in Buffer
  763. //
  764. IconDir = (PGRPICONDIRBASE) GrowBuffer (&GroupIcon, sizeof (GRPICONDIRBASE));
  765. if (!IconDir) {
  766. __leave;
  767. }
  768. IconDir->Reserved = 0;
  769. IconDir->Type = 1;
  770. IconDir->Count = 0;
  771. IconImage = (PICONIMAGE) Buffer->Buf;
  772. IconImageEnd = (PICONIMAGE) (Buffer->Buf + Buffer->End);
  773. p = IconImage;
  774. while (p < IconImageEnd) {
  775. Entry = (PGRPICONDIRENTRY) GrowBuffer (&GroupIcon, sizeof (GRPICONDIRENTRY));
  776. if (!Entry) {
  777. __leave;
  778. }
  779. Header = (PBITMAPINFOHEADER) p;
  780. Entry->Width = (BYTE) Header->biWidth;
  781. Entry->Height = (BYTE) Header->biHeight / 2;
  782. ColorCount = Header->biPlanes * Header->biBitCount;
  783. if (ColorCount >= 8) {
  784. Entry->ColorCount = 0;
  785. } else {
  786. Entry->ColorCount = (BYTE) Power (2, ColorCount);
  787. }
  788. Entry->Planes = Header->biPlanes;
  789. Entry->BitCount = Header->biBitCount;
  790. Entry->BytesInRes = pComputeSizeOfIconImage (p);
  791. if (!NextIconId) {
  792. Entry->ID = 1 + (WORD) ((UINT_PTR) GroupIconId & (0xffff / MAX_RESOLUTIONS)) * MAX_RESOLUTIONS + IconDir->Count;
  793. } else {
  794. Entry->ID = *NextIconId;
  795. }
  796. //
  797. // Add icon to the PE file
  798. //
  799. b = UpdateResourceA (
  800. UpdateHandle,
  801. RT_ICON,
  802. MAKEINTRESOURCE(Entry->ID),
  803. MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
  804. p,
  805. Entry->BytesInRes
  806. );
  807. if (!b) {
  808. LOGA ((LOG_ERROR, "Could not add icon to %s", DestinationFile));
  809. __leave;
  810. }
  811. IconDir->Count += 1;
  812. if (NextIconId) {
  813. *NextIconId += 1;
  814. }
  815. p = (PICONIMAGE) ((PBYTE) p + Entry->BytesInRes);
  816. }
  817. //
  818. // Add the group icon to the PE
  819. //
  820. b = UpdateResourceW (
  821. UpdateHandle,
  822. (PCWSTR) RT_GROUP_ICON,
  823. GroupIconId,
  824. MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
  825. GroupIcon.Buf,
  826. GroupIcon.End
  827. );
  828. if (!b) {
  829. LOGA ((LOG_ERROR, "Unable to add icon to %s", DestinationFile));
  830. __leave;
  831. }
  832. b = TRUE;
  833. }
  834. __finally {
  835. FreeGrowBuffer (&GroupIcon);
  836. }
  837. return b;
  838. }
  839. BOOL
  840. WriteIconImageArrayToPeFileExA (
  841. IN PCSTR DestinationFile,
  842. IN PGROWBUFFER Buffer,
  843. IN PCSTR GroupIconId,
  844. IN PWORD NextIconId, OPTIONAL
  845. IN HANDLE UpdateHandle
  846. )
  847. {
  848. PCWSTR UnicodeDestinationFile;
  849. PCWSTR UnicodeGroupIconId;
  850. BOOL b;
  851. if (!DestinationFile || !Buffer) {
  852. MYASSERT(DestinationFile);
  853. MYASSERT(Buffer);
  854. return FALSE;//BUGBUG: TRUE or FALSE?????
  855. }
  856. if (!pGenerateUnicodeArgs (
  857. DestinationFile,
  858. GroupIconId,
  859. &UnicodeDestinationFile,
  860. &UnicodeGroupIconId
  861. )) {
  862. return FALSE;
  863. }
  864. b = WriteIconImageArrayToPeFileExW (
  865. UnicodeDestinationFile,
  866. Buffer,
  867. UnicodeGroupIconId,
  868. NextIconId,
  869. UpdateHandle
  870. );
  871. PushError();
  872. FreeConvertedStr (UnicodeDestinationFile);
  873. DestroyUnicodeResourceId (UnicodeGroupIconId);
  874. PopError();
  875. return b;
  876. }
  877. BOOL
  878. WriteIconImageArrayToPeFileW (
  879. IN PCWSTR DestinationFile,
  880. IN PGROWBUFFER Buffer,
  881. IN PCWSTR GroupIconId
  882. )
  883. {
  884. HANDLE UpdateHandle = NULL;
  885. BOOL b = FALSE;
  886. if (!DestinationFile || !Buffer) {
  887. MYASSERT(DestinationFile);
  888. MYASSERT(Buffer);
  889. return FALSE;//BUGBUG: TRUE or FALSE?????
  890. }
  891. if (!Buffer->End) {
  892. return TRUE;
  893. }
  894. __try {
  895. //
  896. // Open PE file for update
  897. //
  898. UpdateHandle = BeginUpdateResourceW (DestinationFile, FALSE);
  899. if (!UpdateHandle) {
  900. LOGW ((LOG_ERROR, "Unable to begin resource update of %s", DestinationFile));
  901. __leave;
  902. }
  903. //
  904. // Update the PE file
  905. //
  906. b = WriteIconImageArrayToPeFileExW (DestinationFile, Buffer, (PCWSTR) GroupIconId, NULL, UpdateHandle);
  907. }
  908. __finally {
  909. EndUpdateResource (UpdateHandle, !b);
  910. }
  911. return b;
  912. }
  913. BOOL
  914. WriteIconImageArrayToPeFileA (
  915. IN PCSTR DestinationFile,
  916. IN PGROWBUFFER Buffer,
  917. IN PCSTR GroupIconId
  918. )
  919. {
  920. PCWSTR UnicodeDestinationFile;
  921. PCWSTR UnicodeGroupIconId;
  922. BOOL b;
  923. if (!DestinationFile || !Buffer) {
  924. MYASSERT(DestinationFile);
  925. MYASSERT(Buffer);
  926. return FALSE;//BUGBUG: TRUE or FALSE?????
  927. }
  928. if (!pGenerateUnicodeArgs (
  929. DestinationFile,
  930. GroupIconId,
  931. &UnicodeDestinationFile,
  932. &UnicodeGroupIconId
  933. )) {
  934. return FALSE;
  935. }
  936. b = WriteIconImageArrayToPeFileW (
  937. UnicodeDestinationFile,
  938. Buffer,
  939. UnicodeGroupIconId
  940. );
  941. PushError();
  942. FreeConvertedStr (UnicodeDestinationFile);
  943. DestroyUnicodeResourceId (UnicodeGroupIconId);
  944. PopError();
  945. return b;
  946. }
  947. BOOL
  948. IsFileAnIcoW (
  949. IN PCWSTR FileInQuestion
  950. )
  951. {
  952. PCWSTR p;
  953. DWORD magic;
  954. DWORD bytesRead;
  955. HANDLE icoFileHandle = INVALID_HANDLE_VALUE;
  956. BOOL result = FALSE;
  957. if (!FileInQuestion) {
  958. MYASSERT(FileInQuestion);
  959. return FALSE;
  960. }
  961. p = wcsrchr (FileInQuestion, L'.');
  962. if (p) {
  963. if (StringIMatchW (p, L".ico")) {
  964. return TRUE;
  965. }
  966. }
  967. icoFileHandle = CreateFileW (
  968. FileInQuestion,
  969. GENERIC_READ,
  970. 0,
  971. NULL,
  972. OPEN_EXISTING,
  973. FILE_ATTRIBUTE_NORMAL,
  974. NULL
  975. );
  976. if (icoFileHandle != INVALID_HANDLE_VALUE) {
  977. if (ReadFile (icoFileHandle, (PBYTE)(&magic), sizeof (magic), &bytesRead, NULL)) {
  978. if (bytesRead == sizeof (magic)) {
  979. if (magic != IMAGE_DOS_SIGNATURE) {
  980. result = TRUE;
  981. }
  982. }
  983. }
  984. CloseHandle (icoFileHandle);
  985. }
  986. return result;
  987. }
  988. BOOL
  989. IsFileAnIcoA (
  990. IN PCSTR FileInQuestion
  991. )
  992. {
  993. PCSTR p;
  994. WORD magic;
  995. DWORD bytesRead;
  996. HANDLE icoFileHandle = INVALID_HANDLE_VALUE;
  997. BOOL result = FALSE;
  998. if (!FileInQuestion) {
  999. MYASSERT(FileInQuestion);
  1000. return FALSE;
  1001. }
  1002. p = _mbsrchr (FileInQuestion, '.');
  1003. if (p) {
  1004. if (StringIMatchA (p, ".ico")) {
  1005. return TRUE;
  1006. }
  1007. }
  1008. icoFileHandle = CreateFileA (
  1009. FileInQuestion,
  1010. GENERIC_READ,
  1011. 0,
  1012. NULL,
  1013. OPEN_EXISTING,
  1014. FILE_ATTRIBUTE_NORMAL,
  1015. NULL
  1016. );
  1017. if (icoFileHandle != INVALID_HANDLE_VALUE) {
  1018. if (ReadFile (icoFileHandle, (PBYTE)(&magic), sizeof (magic), &bytesRead, NULL)) {
  1019. if (bytesRead == sizeof (magic)) {
  1020. if (magic != IMAGE_DOS_SIGNATURE) {
  1021. result = TRUE;
  1022. }
  1023. }
  1024. }
  1025. CloseHandle (icoFileHandle);
  1026. }
  1027. return result;
  1028. }
  1029. BOOL
  1030. ExtractIconImageFromFileExW (
  1031. IN PCWSTR ModuleContainingIcon,
  1032. IN PCWSTR GroupIconId,
  1033. IN OUT PGROWBUFFER Buffer,
  1034. IN HANDLE IcoFileHandle, OPTIONAL
  1035. IN HANDLE PeModuleHandle, OPTIONAL
  1036. IN HANDLE NeModuleHandle OPTIONAL
  1037. )
  1038. {
  1039. if(!ModuleContainingIcon){
  1040. MYASSERT(ModuleContainingIcon);
  1041. return FALSE;
  1042. }
  1043. if (IsFileAnIcoW (ModuleContainingIcon)) {
  1044. if (IcoFileHandle) {
  1045. return pGetIconImageArrayFromIcoFileExW (ModuleContainingIcon, Buffer, IcoFileHandle);
  1046. } else {
  1047. return pGetIconImageArrayFromIcoFileW (ModuleContainingIcon, Buffer);
  1048. }
  1049. }
  1050. if (PeModuleHandle) {
  1051. return pGetIconImageArrayFromBinaryExW (
  1052. ModuleContainingIcon,
  1053. GroupIconId,
  1054. Buffer,
  1055. PeModuleHandle,
  1056. NeModuleHandle
  1057. );
  1058. } else {
  1059. return pGetIconImageArrayFromBinaryW (ModuleContainingIcon, GroupIconId, Buffer);
  1060. }
  1061. }
  1062. BOOL
  1063. ExtractIconImageFromFileExA (
  1064. IN PCSTR ModuleContainingIcon,
  1065. IN PCSTR GroupIconId,
  1066. IN OUT PGROWBUFFER Buffer,
  1067. IN HANDLE IcoFileHandle, OPTIONAL
  1068. IN HANDLE PeModuleHandle, OPTIONAL
  1069. IN HANDLE NeModuleHandle OPTIONAL
  1070. )
  1071. {
  1072. if(!ModuleContainingIcon){
  1073. MYASSERT(ModuleContainingIcon);
  1074. return FALSE;
  1075. }
  1076. if (IsFileAnIcoA (ModuleContainingIcon)) {
  1077. if (IcoFileHandle) {
  1078. return pGetIconImageArrayFromIcoFileExA (ModuleContainingIcon, Buffer, IcoFileHandle);
  1079. } else {
  1080. return pGetIconImageArrayFromIcoFileA (ModuleContainingIcon, Buffer);
  1081. }
  1082. }
  1083. if (PeModuleHandle) {
  1084. return pGetIconImageArrayFromBinaryExA (
  1085. ModuleContainingIcon,
  1086. GroupIconId,
  1087. Buffer,
  1088. PeModuleHandle,
  1089. NeModuleHandle
  1090. );
  1091. } else {
  1092. return pGetIconImageArrayFromBinaryA (ModuleContainingIcon, GroupIconId, Buffer);
  1093. }
  1094. }
  1095. BOOL
  1096. ExtractIconImageFromFileW (
  1097. IN PCWSTR ModuleContainingIcon,
  1098. IN PCWSTR GroupIconId,
  1099. IN OUT PGROWBUFFER Buffer
  1100. )
  1101. {
  1102. MYASSERT(ModuleContainingIcon);
  1103. return ExtractIconImageFromFileExW (
  1104. ModuleContainingIcon,
  1105. GroupIconId,
  1106. Buffer,
  1107. NULL,
  1108. NULL,
  1109. NULL
  1110. );
  1111. }
  1112. BOOL
  1113. ExtractIconImageFromFileA (
  1114. IN PCSTR ModuleContainingIcon,
  1115. IN PCSTR GroupIconId,
  1116. IN OUT PGROWBUFFER Buffer
  1117. )
  1118. {
  1119. MYASSERT(ModuleContainingIcon);
  1120. return ExtractIconImageFromFileExA (
  1121. ModuleContainingIcon,
  1122. GroupIconId,
  1123. Buffer,
  1124. NULL,
  1125. NULL,
  1126. NULL
  1127. );
  1128. }
  1129. BOOL
  1130. CALLBACK
  1131. pEnumIconNameProcA (
  1132. HANDLE Module,
  1133. PCSTR Type,
  1134. PSTR Name,
  1135. LONG_PTR lParam
  1136. )
  1137. {
  1138. PGROWBUFFER Buf;
  1139. PCSTR Num;
  1140. CHAR NumBuf[32];
  1141. MYASSERT(lParam);
  1142. Buf = (PGROWBUFFER) lParam;
  1143. if ((UINT_PTR) Name > 0xffff) {
  1144. Num = Name;
  1145. } else {
  1146. Num = NumBuf;
  1147. wsprintfA (NumBuf, "#%u", (UINT) (WORD) Name);
  1148. }
  1149. MultiSzAppendA (Buf, Num);
  1150. return TRUE;
  1151. }
  1152. BOOL
  1153. CALLBACK
  1154. pEnumIconNameProcW (
  1155. HANDLE Module,
  1156. PCWSTR Type,
  1157. PWSTR Name,
  1158. LONG_PTR lParam
  1159. )
  1160. {
  1161. PGROWBUFFER Buf;
  1162. PCWSTR Num;
  1163. WCHAR NumBuf[32];
  1164. MYASSERT(lParam);
  1165. Buf = (PGROWBUFFER) lParam;
  1166. if ((UINT_PTR) Name > 0xffff) {
  1167. Num = Name;
  1168. } else {
  1169. Num = NumBuf;
  1170. wsprintfW (NumBuf, L"#%u", (UINT) (WORD) Name);
  1171. }
  1172. MultiSzAppendW (Buf, Num);
  1173. return TRUE;
  1174. }
  1175. PCSTR
  1176. ExtractIconNamesFromFileExA (
  1177. IN PCSTR ModuleContainingIcons,
  1178. IN OUT PGROWBUFFER NameBuf,
  1179. IN HANDLE Module,
  1180. IN HANDLE Module16
  1181. )
  1182. {
  1183. PCSTR ReturnBuf;
  1184. NameBuf->End = 0;
  1185. if (Module) {
  1186. if (!EnumResourceNamesA (Module, RT_GROUP_ICON, pEnumIconNameProcA, (LONG_PTR) NameBuf)) {
  1187. return NULL;
  1188. }
  1189. } else if (Module16) {
  1190. if (!EnumNeResourceNamesA (Module16, RT_GROUP_ICON, pEnumIconNameProcA, (LONG_PTR) NameBuf)) {
  1191. return NULL;
  1192. }
  1193. } else {
  1194. return NULL;
  1195. }
  1196. MultiSzAppendA (NameBuf, "");
  1197. ReturnBuf = (PCSTR) NameBuf->Buf;
  1198. return ReturnBuf;
  1199. }
  1200. PCWSTR
  1201. ExtractIconNamesFromFileExW (
  1202. IN PCWSTR ModuleContainingIcons,
  1203. IN OUT PGROWBUFFER NameBuf,
  1204. IN HANDLE Module,
  1205. IN HANDLE Module16
  1206. )
  1207. {
  1208. PCWSTR ReturnBuf;
  1209. NameBuf->End = 0;
  1210. if (Module) {
  1211. if (!EnumResourceNamesW (Module, (PCWSTR) RT_GROUP_ICON, pEnumIconNameProcW, (LONG_PTR) NameBuf)) {
  1212. return NULL;
  1213. }
  1214. } else if (Module16) {
  1215. if (!EnumNeResourceNamesW (Module16, (PWSTR) RT_GROUP_ICON, pEnumIconNameProcW, (LONG_PTR) NameBuf)) {
  1216. return NULL;
  1217. }
  1218. } else {
  1219. return NULL;
  1220. }
  1221. MultiSzAppendW (NameBuf, L"");
  1222. ReturnBuf = (PCWSTR) NameBuf->Buf;
  1223. return ReturnBuf;
  1224. }
  1225. PCSTR
  1226. ExtractIconNamesFromFileA (
  1227. IN PCSTR ModuleContainingIcons,
  1228. IN OUT PGROWBUFFER NameBuf
  1229. )
  1230. {
  1231. HANDLE Module = NULL;
  1232. HANDLE Module16 = NULL;
  1233. PCSTR ReturnBuf = NULL;
  1234. if(!ModuleContainingIcons){
  1235. MYASSERT(ModuleContainingIcons);
  1236. return NULL;
  1237. }
  1238. __try {
  1239. Module = LoadLibraryExA (ModuleContainingIcons, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1240. if (!Module) {
  1241. Module16 = OpenNeFileA (ModuleContainingIcons);
  1242. if (!Module16) {
  1243. DEBUGMSGA ((DBG_WARNING, "Can't load %s, error %u", ModuleContainingIcons, GetLastError()));
  1244. __leave;
  1245. }
  1246. }
  1247. ReturnBuf = ExtractIconNamesFromFileExA (ModuleContainingIcons, NameBuf, Module, Module16);
  1248. }
  1249. __finally {
  1250. if (Module) {
  1251. FreeLibrary (Module);
  1252. }
  1253. if (Module16) {
  1254. CloseNeFile (Module16);
  1255. }
  1256. }
  1257. return ReturnBuf;
  1258. }
  1259. PCWSTR
  1260. ExtractIconNamesFromFileW (
  1261. IN PCWSTR ModuleContainingIcons,
  1262. IN OUT PGROWBUFFER NameBuf
  1263. )
  1264. {
  1265. HANDLE Module = NULL;
  1266. HANDLE Module16 = NULL;
  1267. PCWSTR ReturnBuf = NULL;
  1268. if(!ModuleContainingIcons){
  1269. MYASSERT(ModuleContainingIcons);
  1270. return NULL;
  1271. }
  1272. __try {
  1273. Module = LoadLibraryExW (ModuleContainingIcons, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1274. if (!Module) {
  1275. Module16 = OpenNeFileW (ModuleContainingIcons);
  1276. if (!Module16) {
  1277. DEBUGMSGW ((DBG_WARNING, "Can't load %s, error %u", ModuleContainingIcons, GetLastError()));
  1278. __leave;
  1279. }
  1280. }
  1281. ReturnBuf = ExtractIconNamesFromFileExW (ModuleContainingIcons, NameBuf, Module, Module16);
  1282. }
  1283. __finally {
  1284. if (Module) {
  1285. FreeLibrary (Module);
  1286. }
  1287. if (Module16) {
  1288. CloseNeFile (Module16);
  1289. }
  1290. }
  1291. return ReturnBuf;
  1292. }
  1293. VOID
  1294. pInitContextA (
  1295. PICON_EXTRACT_CONTEXTA Context
  1296. )
  1297. {
  1298. MYASSERT(Context);
  1299. ZeroMemory (Context, sizeof (ICON_EXTRACT_CONTEXTA));
  1300. Context->GroupId = 1;
  1301. Context->IconId = 1;
  1302. Context->IconImageFile = INVALID_HANDLE_VALUE;
  1303. }
  1304. VOID
  1305. pInitContextW (
  1306. PICON_EXTRACT_CONTEXTW Context
  1307. )
  1308. {
  1309. MYASSERT(Context);
  1310. ZeroMemory (Context, sizeof (ICON_EXTRACT_CONTEXTW));
  1311. Context->GroupId = 1;
  1312. Context->IconId = 1;
  1313. Context->IconImageFile = INVALID_HANDLE_VALUE;
  1314. }
  1315. BOOL
  1316. BeginIconExtractionA (
  1317. OUT PICON_EXTRACT_CONTEXTA Context,
  1318. IN PCSTR DestFile OPTIONAL
  1319. )
  1320. {
  1321. MYASSERT(Context);
  1322. pInitContextA (Context);
  1323. if (DestFile) {
  1324. Context->Update = BeginUpdateResourceA (DestFile, FALSE);
  1325. if (!Context->Update) {
  1326. LOGA ((LOG_ERROR, "Unable to begin resource update of %s", DestFile));
  1327. return FALSE;
  1328. }
  1329. if(strlen(DestFile) >= ARRAYSIZE(Context->DestFile)){
  1330. MYASSERT(strlen(DestFile) < ARRAYSIZE(Context->DestFile));
  1331. return FALSE;
  1332. }
  1333. StringCopyA (Context->DestFile, DestFile);
  1334. }
  1335. return TRUE;
  1336. }
  1337. BOOL
  1338. BeginIconExtractionW (
  1339. OUT PICON_EXTRACT_CONTEXTW Context,
  1340. IN PCWSTR DestFile OPTIONAL
  1341. )
  1342. {
  1343. MYASSERT(Context);
  1344. pInitContextW (Context);
  1345. if (DestFile) {
  1346. Context->Update = BeginUpdateResourceW (DestFile, FALSE);
  1347. if (!Context->Update) {
  1348. LOGW ((LOG_ERROR, "Unable to begin resource update of %s", DestFile));
  1349. return FALSE;
  1350. }
  1351. if(wcslen(DestFile) >= ARRAYSIZE(Context->DestFile)){
  1352. MYASSERT(wcslen(DestFile) < ARRAYSIZE(Context->DestFile));
  1353. return FALSE;
  1354. }
  1355. StringCopyW (Context->DestFile, DestFile);
  1356. }
  1357. return TRUE;
  1358. }
  1359. BOOL
  1360. pLoadBinaryImageA (
  1361. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1362. IN PCSTR IconFile
  1363. )
  1364. {
  1365. MYASSERT(Context);
  1366. MYASSERT(IconFile);
  1367. if (Context->Module || Context->Module16) {
  1368. if (StringIMatchA (Context->ModuleName, IconFile)) {
  1369. return TRUE;
  1370. }
  1371. }
  1372. if (Context->Module) {
  1373. FreeLibrary (Context->Module);
  1374. Context->Module = NULL;
  1375. }
  1376. if (Context->Module16) {
  1377. CloseNeFile (Context->Module16);
  1378. Context->Module16 = NULL;
  1379. }
  1380. Context->Module = LoadLibraryExA (IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1381. if (Context->Module) {
  1382. StringCopyA (Context->ModuleName, IconFile);
  1383. } else {
  1384. Context->Module16 = OpenNeFileA (IconFile);
  1385. if (Context->Module16) {
  1386. if(strlen(IconFile) >= ARRAYSIZE(Context->ModuleName)){
  1387. MYASSERT(strlen(IconFile) < ARRAYSIZE(Context->ModuleName));
  1388. return FALSE;
  1389. }
  1390. StringCopyA (Context->ModuleName, IconFile);
  1391. } else {
  1392. Context->ModuleName[0] = 0;
  1393. }
  1394. }
  1395. return Context->Module != NULL || Context->Module16 != NULL;
  1396. }
  1397. BOOL
  1398. pLoadBinaryImageW (
  1399. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1400. IN PCWSTR IconFile
  1401. )
  1402. {
  1403. if (Context->Module || Context->Module16) {
  1404. if (StringIMatchW (Context->ModuleName, IconFile)) {
  1405. return TRUE;
  1406. }
  1407. }
  1408. if (Context->Module) {
  1409. FreeLibrary (Context->Module);
  1410. }
  1411. if (Context->Module16) {
  1412. CloseNeFile (Context->Module16);
  1413. Context->Module16 = NULL;
  1414. }
  1415. Context->Module = LoadLibraryExW (IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1416. if (Context->Module) {
  1417. StringCopyW (Context->ModuleName, IconFile);
  1418. } else {
  1419. Context->Module16 = OpenNeFileW (IconFile);
  1420. if (Context->Module16) {
  1421. if(wcslen(IconFile) >= ARRAYSIZE(Context->ModuleName)){
  1422. MYASSERT(wcslen(IconFile) < ARRAYSIZE(Context->ModuleName));
  1423. return FALSE;
  1424. }
  1425. StringCopyW (Context->ModuleName, IconFile);
  1426. } else {
  1427. Context->ModuleName[0] = 0;
  1428. }
  1429. }
  1430. return Context->Module != NULL || Context->Module16 != NULL;
  1431. }
  1432. BOOL
  1433. pOpenIcoFileA (
  1434. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1435. IN PCSTR IconFile
  1436. )
  1437. {
  1438. MYASSERT(Context);
  1439. MYASSERT(IconFile);
  1440. if (Context->IcoFile) {
  1441. if (StringIMatchA (Context->IcoFileName, IconFile)) {
  1442. return TRUE;
  1443. }
  1444. }
  1445. if (Context->IcoFile) {
  1446. CloseHandle (Context->IcoFile);
  1447. }
  1448. Context->IcoFile = CreateFileA (IconFile, GENERIC_READ, 0, NULL,
  1449. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1450. if (Context->IcoFile == INVALID_HANDLE_VALUE) {
  1451. Context->IcoFile = NULL;
  1452. Context->IcoFileName[0] = 0;
  1453. } else {
  1454. if(strlen(IconFile) >= ARRAYSIZE(Context->IcoFileName)){
  1455. MYASSERT(strlen(IconFile) < ARRAYSIZE(Context->IcoFileName));
  1456. return FALSE;
  1457. }
  1458. StringCopyA (Context->IcoFileName, IconFile);
  1459. }
  1460. return Context->IcoFile != NULL;
  1461. }
  1462. BOOL
  1463. pOpenIcoFileW (
  1464. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1465. IN PCWSTR IconFile
  1466. )
  1467. {
  1468. MYASSERT(Context);
  1469. MYASSERT(IconFile);
  1470. if (Context->IcoFile) {
  1471. if (StringIMatchW (Context->IcoFileName, IconFile)) {
  1472. return TRUE;
  1473. }
  1474. }
  1475. if (Context->IcoFile) {
  1476. CloseHandle (Context->IcoFile);
  1477. }
  1478. Context->IcoFile = CreateFileW (IconFile, GENERIC_READ, 0, NULL,
  1479. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1480. if (Context->IcoFile == INVALID_HANDLE_VALUE) {
  1481. Context->IcoFile = NULL;
  1482. Context->IcoFileName[0] = 0;
  1483. } else {
  1484. if(wcslen(IconFile) >= ARRAYSIZE(Context->IcoFileName)){
  1485. MYASSERT(wcslen(IconFile) < ARRAYSIZE(Context->IcoFileName));
  1486. return FALSE;
  1487. }
  1488. StringCopyW (Context->IcoFileName, IconFile);
  1489. }
  1490. return Context->IcoFile != NULL;
  1491. }
  1492. BOOL
  1493. pOpenIconImageA (
  1494. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1495. IN PCSTR FileToOpen,
  1496. OUT PBOOL IsIco, OPTIONAL
  1497. OUT PBOOL Is16Bit OPTIONAL
  1498. )
  1499. {
  1500. MYASSERT(Context);
  1501. MYASSERT(FileToOpen);
  1502. if (Is16Bit) {
  1503. *Is16Bit = FALSE;
  1504. }
  1505. if (IsFileAnIcoA (FileToOpen)) {
  1506. if (IsIco) {
  1507. *IsIco = TRUE;
  1508. }
  1509. return pOpenIcoFileA (Context, FileToOpen);
  1510. }
  1511. if (IsIco) {
  1512. *IsIco = FALSE;
  1513. }
  1514. if (pLoadBinaryImageA (Context, FileToOpen)) {
  1515. if (Context->Module16 && Is16Bit) {
  1516. *Is16Bit = TRUE;
  1517. }
  1518. return TRUE;
  1519. }
  1520. return FALSE;
  1521. }
  1522. BOOL
  1523. pOpenIconImageW (
  1524. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1525. IN PCWSTR FileToOpen,
  1526. OUT PBOOL IsIco, OPTIONAL
  1527. OUT PBOOL Is16Bit OPTIONAL
  1528. )
  1529. {
  1530. MYASSERT(Context);
  1531. MYASSERT(FileToOpen);
  1532. if (Is16Bit) {
  1533. *Is16Bit = FALSE;
  1534. }
  1535. if (IsFileAnIcoW (FileToOpen)) {
  1536. if (IsIco) {
  1537. *IsIco = TRUE;
  1538. }
  1539. return pOpenIcoFileW (Context, FileToOpen);
  1540. }
  1541. if (IsIco) {
  1542. *IsIco = FALSE;
  1543. }
  1544. if (pLoadBinaryImageW (Context, FileToOpen)) {
  1545. if (Context->Module16 && Is16Bit) {
  1546. *Is16Bit = TRUE;
  1547. }
  1548. return TRUE;
  1549. }
  1550. return FALSE;
  1551. }
  1552. BOOL
  1553. OpenIconImageFileA (
  1554. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1555. IN PCSTR FileName,
  1556. IN BOOL SaveMode
  1557. )
  1558. {
  1559. if(!Context || !FileName){
  1560. MYASSERT(Context);
  1561. MYASSERT(FileName);
  1562. return FALSE;
  1563. }
  1564. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  1565. CloseHandle (Context->IconImageFile);
  1566. Context->IconImageFileName[0] = 0;
  1567. }
  1568. if (SaveMode) {
  1569. Context->IconImageFile = CreateFileA (
  1570. FileName,
  1571. GENERIC_WRITE,
  1572. 0,
  1573. NULL,
  1574. CREATE_ALWAYS,
  1575. FILE_ATTRIBUTE_NORMAL,
  1576. NULL
  1577. );
  1578. } else {
  1579. Context->IconImageFile = CreateFileA (
  1580. FileName,
  1581. GENERIC_READ,
  1582. 0,
  1583. NULL,
  1584. OPEN_EXISTING,
  1585. FILE_ATTRIBUTE_NORMAL,
  1586. NULL
  1587. );
  1588. }
  1589. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  1590. if(strlen(FileName) >= ARRAYSIZE(Context->IconImageFileName)){
  1591. MYASSERT(strlen(FileName) < ARRAYSIZE(Context->IconImageFileName));
  1592. return FALSE;
  1593. }
  1594. StringCopyA (Context->IconImageFileName, FileName);
  1595. Context->SaveMode = SaveMode;
  1596. return TRUE;
  1597. }
  1598. return FALSE;
  1599. }
  1600. BOOL
  1601. OpenIconImageFileW (
  1602. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1603. IN PCWSTR FileName,
  1604. IN BOOL SaveMode
  1605. )
  1606. {
  1607. if(!Context || !FileName){
  1608. MYASSERT(Context);
  1609. MYASSERT(FileName);
  1610. return FALSE;
  1611. }
  1612. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  1613. CloseHandle (Context->IconImageFile);
  1614. Context->IconImageFileName[0] = 0;
  1615. }
  1616. if (SaveMode) {
  1617. Context->IconImageFile = CreateFileW (
  1618. FileName,
  1619. GENERIC_WRITE,
  1620. 0,
  1621. NULL,
  1622. CREATE_ALWAYS,
  1623. FILE_ATTRIBUTE_NORMAL,
  1624. NULL
  1625. );
  1626. } else {
  1627. Context->IconImageFile = CreateFileW (
  1628. FileName,
  1629. GENERIC_READ,
  1630. 0,
  1631. NULL,
  1632. OPEN_EXISTING,
  1633. FILE_ATTRIBUTE_NORMAL,
  1634. NULL
  1635. );
  1636. }
  1637. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  1638. if(wcslen(FileName) >= ARRAYSIZE(Context->IconImageFileName)){
  1639. MYASSERT(wcslen(FileName) < ARRAYSIZE(Context->IconImageFileName));
  1640. return FALSE;
  1641. }
  1642. StringCopyW (Context->IconImageFileName, FileName);
  1643. Context->SaveMode = SaveMode;
  1644. return TRUE;
  1645. }
  1646. return FALSE;
  1647. }
  1648. BOOL
  1649. pGetIconImageArrayFromFileA (
  1650. IN PICON_EXTRACT_CONTEXTA Context
  1651. )
  1652. {
  1653. DWORD Size;
  1654. PBYTE Dest;
  1655. HANDLE File;
  1656. MYASSERT(Context);
  1657. File = Context->IconImageFile;
  1658. if (!ReadBinaryBlock (File, &Size, sizeof (DWORD))) {
  1659. return FALSE;
  1660. }
  1661. Context->IconImages.End = 0;
  1662. Dest = GrowBuffer (&Context->IconImages, Size);
  1663. if (!Dest) {
  1664. return FALSE;
  1665. }
  1666. return ReadBinaryBlock (File, Dest, Size);
  1667. }
  1668. BOOL
  1669. pGetIconImageArrayFromFileW (
  1670. IN PICON_EXTRACT_CONTEXTW Context
  1671. )
  1672. {
  1673. DWORD Size;
  1674. PBYTE Dest;
  1675. HANDLE File;
  1676. MYASSERT(Context);
  1677. File = Context->IconImageFile;
  1678. if (!ReadBinaryBlock (File, &Size, sizeof (DWORD))) {
  1679. return FALSE;
  1680. }
  1681. Context->IconImages.End = 0;
  1682. Dest = GrowBuffer (&Context->IconImages, Size);
  1683. if (!Dest) {
  1684. return FALSE;
  1685. }
  1686. return ReadBinaryBlock (File, Dest, Size);
  1687. }
  1688. BOOL
  1689. pPutIconImageArrayInFileA (
  1690. IN PICON_EXTRACT_CONTEXTA Context
  1691. )
  1692. {
  1693. HANDLE File;
  1694. MYASSERT(Context);
  1695. File = Context->IconImageFile;
  1696. if (!Context->IconImages.End) {
  1697. DEBUGMSGA_IF ((
  1698. Context->ModuleName[0],
  1699. DBG_WARNING,
  1700. "Ignoring empty icon in %s",
  1701. Context->ModuleName
  1702. ));
  1703. return TRUE;
  1704. }
  1705. if (!pWriteBinaryBlock (File, &Context->IconImages.End, sizeof (DWORD))) {
  1706. return FALSE;
  1707. }
  1708. return pWriteBinaryBlock (File, Context->IconImages.Buf, Context->IconImages.End);
  1709. }
  1710. BOOL
  1711. pPutIconImageArrayInFileW (
  1712. IN PICON_EXTRACT_CONTEXTW Context
  1713. )
  1714. {
  1715. HANDLE File;
  1716. MYASSERT(Context);
  1717. File = Context->IconImageFile;
  1718. if (!Context->IconImages.End) {
  1719. DEBUGMSGW_IF ((
  1720. Context->ModuleName[0],
  1721. DBG_WARNING,
  1722. "Ignoring empty icon in %s",
  1723. Context->ModuleName
  1724. ));
  1725. return TRUE;
  1726. }
  1727. if (!pWriteBinaryBlock (File, &Context->IconImages.End, sizeof (DWORD))) {
  1728. return FALSE;
  1729. }
  1730. return pWriteBinaryBlock (File, Context->IconImages.Buf, Context->IconImages.End);
  1731. }
  1732. PCSTR
  1733. pFindResourceIdFromIndexA (
  1734. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1735. IN PCSTR FileContainingIcon,
  1736. IN INT ResourceIndex,
  1737. OUT PSTR Buffer,
  1738. IN UINT BufferSize
  1739. )
  1740. {
  1741. PCSTR ImageList;
  1742. MYASSERT(Context);
  1743. MYASSERT(FileContainingIcon);
  1744. MYASSERT(Buffer);
  1745. MYASSERT(BufferSize);
  1746. if (!pLoadBinaryImageA (Context, FileContainingIcon)) {
  1747. return NULL;
  1748. }
  1749. if (ResourceIndex < 0) {
  1750. MYASSERT(BufferSize > ARRAYSIZE("-2147483648\0"));
  1751. wsprintfA (Buffer, "#%i", -ResourceIndex);
  1752. return Buffer;
  1753. } else {
  1754. *Buffer = 0;
  1755. }
  1756. ImageList = ExtractIconNamesFromFileExA (
  1757. FileContainingIcon,
  1758. &Context->IconList,
  1759. Context->Module,
  1760. Context->Module16
  1761. );
  1762. while (ImageList) {
  1763. if (!ResourceIndex) {
  1764. if(BufferSize <= strlen(ImageList)){
  1765. MYASSERT(BufferSize > strlen(ImageList));
  1766. return NULL;
  1767. }
  1768. StringCopyA (Buffer, ImageList);
  1769. break;
  1770. }
  1771. ResourceIndex--;
  1772. }
  1773. return *Buffer ? Buffer : NULL;
  1774. }
  1775. PCWSTR
  1776. pFindResourceIdFromIndexW (
  1777. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1778. IN PCWSTR FileContainingIcon,
  1779. IN INT ResourceIndex,
  1780. OUT PWSTR Buffer,
  1781. IN UINT BufferSize
  1782. )
  1783. {
  1784. PCWSTR ImageList;
  1785. MYASSERT(Context);
  1786. MYASSERT(FileContainingIcon);
  1787. MYASSERT(Buffer);
  1788. MYASSERT(BufferSize);
  1789. if (!pLoadBinaryImageW (Context, FileContainingIcon)) {
  1790. return NULL;
  1791. }
  1792. if (ResourceIndex < 0) {
  1793. MYASSERT(BufferSize > ARRAYSIZE("-2147483648\0"));
  1794. wsprintfW (Buffer, L"#%i", -ResourceIndex);
  1795. return Buffer;
  1796. } else {
  1797. *Buffer = 0;
  1798. }
  1799. ImageList = ExtractIconNamesFromFileExW (
  1800. FileContainingIcon,
  1801. &Context->IconList,
  1802. Context->Module,
  1803. Context->Module16
  1804. );
  1805. while (ImageList) {
  1806. if (!ResourceIndex) {
  1807. if(BufferSize <= wcslen(ImageList)){
  1808. MYASSERT(BufferSize > wcslen(ImageList));
  1809. return NULL;
  1810. }
  1811. StringCopyW (Buffer, ImageList);
  1812. break;
  1813. }
  1814. ResourceIndex--;
  1815. }
  1816. return *Buffer ? Buffer : NULL;
  1817. }
  1818. BOOL
  1819. CopyIconA (
  1820. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1821. IN PCSTR FileContainingIcon, OPTIONAL
  1822. IN PCSTR ResourceId, OPTIONAL
  1823. IN INT ResourceIndex OPTIONAL
  1824. )
  1825. {
  1826. BOOL IsIco;
  1827. BOOL b;
  1828. CHAR Buffer[256];
  1829. if (!Context || Context->Error) {
  1830. MYASSERT(Context);
  1831. return FALSE;
  1832. }
  1833. if (!ResourceId && FileContainingIcon) {
  1834. if (!IsFileAnIco (FileContainingIcon)) {
  1835. ResourceId = pFindResourceIdFromIndexA (
  1836. Context,
  1837. FileContainingIcon,
  1838. ResourceIndex,
  1839. Buffer,
  1840. ARRAYSIZE(Buffer)
  1841. );
  1842. if (!ResourceId) {
  1843. return FALSE;
  1844. }
  1845. }
  1846. }
  1847. if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
  1848. !Context->SaveMode
  1849. ) {
  1850. //
  1851. // Get icon image from the icon image array file
  1852. //
  1853. b = pGetIconImageArrayFromFileA (Context);
  1854. } else {
  1855. //
  1856. // Get icon image from source file
  1857. //
  1858. if (!pOpenIconImageA (Context, FileContainingIcon, &IsIco, NULL)) {
  1859. return FALSE;
  1860. }
  1861. if (IsIco) {
  1862. b = pGetIconImageArrayFromIcoFileExA (
  1863. Context->IcoFileName,
  1864. &Context->IconImages,
  1865. Context->IcoFile
  1866. );
  1867. } else {
  1868. b = pGetIconImageArrayFromBinaryExA (
  1869. Context->ModuleName,
  1870. ResourceId,
  1871. &Context->IconImages,
  1872. Context->Module,
  1873. Context->Module16
  1874. );
  1875. }
  1876. }
  1877. if (b) {
  1878. if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
  1879. Context->SaveMode
  1880. ) {
  1881. //
  1882. // Save icon to icon image array file
  1883. //
  1884. b = pPutIconImageArrayInFileA (Context);
  1885. } else {
  1886. //
  1887. // Save icon to PE file
  1888. //
  1889. b = WriteIconImageArrayToPeFileExA (
  1890. Context->DestFile,
  1891. &Context->IconImages,
  1892. (PCSTR) Context->GroupId,
  1893. &Context->IconId,
  1894. Context->Update
  1895. );
  1896. }
  1897. if (!b) {
  1898. Context->Error = TRUE;
  1899. } else {
  1900. Context->GroupId++;
  1901. }
  1902. }
  1903. return b;
  1904. }
  1905. BOOL
  1906. CopyIconW (
  1907. IN OUT PICON_EXTRACT_CONTEXTW Context,
  1908. IN PCWSTR FileContainingIcon, // OPTIONAL if using an icon image file
  1909. IN PCWSTR ResourceId, // OPTIONAL if FileContainingIcon is an ico
  1910. IN INT ResourceIndex OPTIONAL
  1911. )
  1912. {
  1913. BOOL IsIco;
  1914. BOOL b;
  1915. WCHAR Buffer[256];
  1916. if (!Context || Context->Error) {
  1917. MYASSERT(Context);
  1918. return FALSE;
  1919. }
  1920. if (!ResourceId && FileContainingIcon) {
  1921. if (!IsFileAnIcoW (FileContainingIcon)) {
  1922. ResourceId = pFindResourceIdFromIndexW (
  1923. Context,
  1924. FileContainingIcon,
  1925. ResourceIndex,
  1926. Buffer,
  1927. ARRAYSIZE(Buffer)
  1928. );
  1929. if (!ResourceId) {
  1930. return FALSE;
  1931. }
  1932. }
  1933. }
  1934. if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
  1935. !Context->SaveMode
  1936. ) {
  1937. //
  1938. // Get icon image from the icon image array file
  1939. //
  1940. b = pGetIconImageArrayFromFileW (Context);
  1941. } else {
  1942. //
  1943. // Get icon image from source file
  1944. //
  1945. if (!pOpenIconImageW (Context, FileContainingIcon, &IsIco, NULL)) {
  1946. return FALSE;
  1947. }
  1948. if (IsIco) {
  1949. b = pGetIconImageArrayFromIcoFileExW (
  1950. Context->IcoFileName,
  1951. &Context->IconImages,
  1952. Context->IcoFile
  1953. );
  1954. } else {
  1955. b = pGetIconImageArrayFromBinaryExW (
  1956. Context->ModuleName,
  1957. ResourceId,
  1958. &Context->IconImages,
  1959. Context->Module,
  1960. Context->Module16
  1961. );
  1962. }
  1963. }
  1964. if (b) {
  1965. if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
  1966. Context->SaveMode
  1967. ) {
  1968. //
  1969. // Save icon to icon image array file
  1970. //
  1971. b = pPutIconImageArrayInFileW (Context);
  1972. } else {
  1973. //
  1974. // Save icon to PE file
  1975. //
  1976. b = WriteIconImageArrayToPeFileExW (
  1977. Context->DestFile,
  1978. &Context->IconImages,
  1979. (PCWSTR) Context->GroupId,
  1980. &Context->IconId,
  1981. Context->Update
  1982. );
  1983. }
  1984. if (!b) {
  1985. Context->Error = TRUE;
  1986. } else {
  1987. Context->GroupId++;
  1988. }
  1989. }
  1990. return b;
  1991. }
  1992. BOOL
  1993. CopyAllIconsA (
  1994. IN OUT PICON_EXTRACT_CONTEXTA Context,
  1995. IN PCSTR FileContainingIcons
  1996. )
  1997. {
  1998. MULTISZ_ENUMA e;
  1999. BOOL IsIco;
  2000. PCSTR IconList;
  2001. BOOL b = TRUE;
  2002. if (!Context || Context->Error) {
  2003. MYASSERT(Context);
  2004. return FALSE;
  2005. }
  2006. if(!FileContainingIcons){
  2007. MYASSERT(FileContainingIcons);
  2008. return FALSE;
  2009. }
  2010. if (!pOpenIconImageA (Context, FileContainingIcons, &IsIco, NULL)) {
  2011. return FALSE;
  2012. }
  2013. if (IsIco) {
  2014. return CopyIconA (Context, FileContainingIcons, NULL, 0);
  2015. }
  2016. IconList = ExtractIconNamesFromFileExA (
  2017. FileContainingIcons,
  2018. &Context->IconList,
  2019. Context->Module,
  2020. Context->Module16
  2021. );
  2022. if (!IconList) {
  2023. return FALSE;
  2024. }
  2025. if (EnumFirstMultiSzA (&e, IconList)) {
  2026. do {
  2027. b = CopyIconA (Context, FileContainingIcons, e.CurrentString, 0);
  2028. if (!b) {
  2029. break;
  2030. }
  2031. } while (EnumNextMultiSzA (&e));
  2032. }
  2033. return b;
  2034. }
  2035. BOOL
  2036. CopyAllIconsW (
  2037. IN OUT PICON_EXTRACT_CONTEXTW Context,
  2038. IN PCWSTR FileContainingIcons
  2039. )
  2040. {
  2041. MULTISZ_ENUMW e;
  2042. BOOL IsIco;
  2043. PCWSTR IconList;
  2044. BOOL b = TRUE;
  2045. if (!Context || Context->Error) {
  2046. MYASSERT(Context);
  2047. return FALSE;
  2048. }
  2049. if(!FileContainingIcons){
  2050. MYASSERT(FileContainingIcons);
  2051. return FALSE;
  2052. }
  2053. if (!pOpenIconImageW (Context, FileContainingIcons, &IsIco, NULL)) {
  2054. return FALSE;
  2055. }
  2056. if (IsIco) {
  2057. return CopyIconW (Context, FileContainingIcons, NULL, 0);
  2058. }
  2059. IconList = ExtractIconNamesFromFileExW (
  2060. FileContainingIcons,
  2061. &Context->IconList,
  2062. Context->Module,
  2063. Context->Module16
  2064. );
  2065. if (!IconList) {
  2066. return FALSE;
  2067. }
  2068. if (EnumFirstMultiSzW (&e, IconList)) {
  2069. do {
  2070. b = CopyIconW (Context, FileContainingIcons, e.CurrentString, 0);
  2071. if (!b) {
  2072. break;
  2073. }
  2074. } while (EnumNextMultiSzW (&e));
  2075. }
  2076. return b;
  2077. }
  2078. BOOL
  2079. EndIconExtractionA (
  2080. IN OUT PICON_EXTRACT_CONTEXTA Context
  2081. )
  2082. {
  2083. BOOL b = FALSE;
  2084. if(!Context){
  2085. MYASSERT(Context);
  2086. return FALSE;
  2087. }
  2088. if (Context->Update) {
  2089. b = EndUpdateResource (Context->Update, Context->Error);
  2090. }
  2091. if (Context->Module) {
  2092. FreeLibrary (Context->Module);
  2093. }
  2094. if (Context->Module16) {
  2095. CloseNeFile (Context->Module16);
  2096. }
  2097. if (Context->IcoFile) {
  2098. FreeLibrary (Context->IcoFile);
  2099. }
  2100. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  2101. CloseHandle (Context->IconImageFile);
  2102. }
  2103. FreeGrowBuffer (&Context->IconImages);
  2104. FreeGrowBuffer (&Context->IconList);
  2105. pInitContextA (Context);
  2106. return b;
  2107. }
  2108. BOOL
  2109. EndIconExtractionW (
  2110. IN OUT PICON_EXTRACT_CONTEXTW Context
  2111. )
  2112. {
  2113. BOOL b = FALSE;
  2114. if(!Context){
  2115. MYASSERT(Context);
  2116. return FALSE;
  2117. }
  2118. if (Context->Update) {
  2119. b = EndUpdateResource (Context->Update, Context->Error);
  2120. }
  2121. if (Context->Module) {
  2122. FreeLibrary (Context->Module);
  2123. }
  2124. if (Context->Module16) {
  2125. CloseNeFile (Context->Module16);
  2126. }
  2127. if (Context->IcoFile) {
  2128. FreeLibrary (Context->IcoFile);
  2129. }
  2130. if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
  2131. CloseHandle (Context->IconImageFile);
  2132. }
  2133. FreeGrowBuffer (&Context->IconImages);
  2134. FreeGrowBuffer (&Context->IconList);
  2135. pInitContextW (Context);
  2136. return b;
  2137. }