Subversion Repositories filter_foundry

Rev

Rev 311 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.         This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.         Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
  4.         Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
  5.  
  6.         This program is free software; you can redistribute it and/or modify
  7.         it under the terms of the GNU General Public License as published by
  8.         the Free Software Foundation; either version 2 of the License, or
  9.         (at your option) any later version.
  10.  
  11.         This program is distributed in the hope that it will be useful,
  12.         but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.         GNU General Public License for more details.
  15.  
  16.         You should have received a copy of the GNU General Public License
  17.         along with this program; if not, write to the Free Software
  18.         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #ifndef _CRT_SECURE_NO_WARNINGS
  22. #define _CRT_SECURE_NO_WARNINGS
  23. #endif
  24.  
  25. #include <iostream>
  26. #include <windows.h>
  27.  
  28. bool update_pe_timestamp(LPCTSTR filename, time_t timestamp) {
  29.         size_t peoffset;
  30.         FILE* fptr;
  31.  
  32.         fptr = _wfopen(filename, L"rb+");
  33.         if (fptr == NULL) return false;
  34.  
  35.         fseek(fptr, 0x3C, SEEK_SET);
  36.         fread(&peoffset, sizeof(peoffset), 1, fptr);
  37.  
  38.         fseek(fptr, (long)peoffset + 8, SEEK_SET);
  39.         fwrite(&timestamp, sizeof(time_t), 1, fptr);
  40.  
  41.         fclose(fptr);
  42.  
  43.         return true;
  44. }
  45.  
  46. //DOS .EXE header
  47. struct image_dos_header
  48. {
  49.         uint16_t e_magic;                     // Magic number
  50.         uint16_t e_cblp;                      // Bytes on last page of file
  51.         uint16_t e_cp;                        // Pages in file
  52.         uint16_t e_crlc;                      // Relocations
  53.         uint16_t e_cparhdr;                   // Size of header in paragraphs
  54.         uint16_t e_minalloc;                  // Minimum extra paragraphs needed
  55.         uint16_t e_maxalloc;                  // Maximum extra paragraphs needed
  56.         uint16_t e_ss;                        // Initial (relative) SS value
  57.         uint16_t e_sp;                        // Initial SP value
  58.         uint16_t e_csum;                      // Checksum
  59.         uint16_t e_ip;                        // Initial IP value
  60.         uint16_t e_cs;                        // Initial (relative) CS value
  61.         uint16_t e_lfarlc;                    // File address of relocation table
  62.         uint16_t e_ovno;                      // Overlay number
  63.         uint16_t e_res[4];                    // Reserved words
  64.         uint16_t e_oemid;                     // OEM identifier (for e_oeminfo)
  65.         uint16_t e_oeminfo;                   // OEM information; e_oemid specific
  66.         uint16_t e_res2[10];                  // Reserved words
  67.         int32_t  e_lfanew;                    // File address of new exe header
  68. };
  69.  
  70. struct image_file_header
  71. {
  72.         uint16_t Machine;
  73.         uint16_t NumberOfSections;
  74.         uint32_t TimeDateStamp;
  75.         uint32_t PointerToSymbolTable;
  76.         uint32_t NumberOfSymbols;
  77.         uint16_t SizeOfOptionalHeader;
  78.         uint16_t Characteristics;
  79. };
  80.  
  81. uint32_t calculate_checksum(LPCTSTR filename) {
  82.         //Calculate checksum of image
  83.         // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
  84.         // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
  85.         // Converted from C++ to C by Daniel Marschall
  86.  
  87.         FILE* fptr;
  88.         unsigned long long checksum = 0;
  89.         struct image_dos_header header;
  90.         size_t filesize;
  91.         unsigned long long top;
  92.         unsigned long pe_checksum_pos;
  93.         static const unsigned long checksum_pos_in_optional_headers = 64;
  94.         size_t i;
  95.  
  96.         fptr = _wfopen(filename, L"rb");
  97.         if (fptr == NULL) return 0x00000000;
  98.  
  99.         //Read DOS header
  100.         fseek(fptr, 0, SEEK_SET);
  101.         fread(&header, sizeof(struct image_dos_header), 1, fptr);
  102.  
  103.         //Calculate PE checksum
  104.         fseek(fptr, 0, SEEK_SET);
  105.         top = 0xFFFFFFFF;
  106.         top++;
  107.  
  108.         //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
  109.         //Calculate real PE headers "CheckSum" field position
  110.         //Sum is safe here
  111.         pe_checksum_pos = header.e_lfanew + sizeof(struct image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
  112.  
  113.         //Calculate checksum for each byte of file
  114.         fseek(fptr, 0L, SEEK_END);
  115.         filesize = ftell(fptr);
  116.         fseek(fptr, 0L, SEEK_SET);
  117.         for (i = 0; i < filesize; i += 4)
  118.         {
  119.                 unsigned long dw = 0;
  120.  
  121.                 //Read DWORD from file
  122.                 fread(&dw, sizeof(dw), 1, fptr);
  123.                 //Skip "CheckSum" DWORD
  124.                 if (i == pe_checksum_pos)
  125.                         continue;
  126.  
  127.                 //Calculate checksum
  128.                 checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
  129.                 if (checksum > top)
  130.                         checksum = (checksum & 0xffffffff) + (checksum >> 32);
  131.         }
  132.  
  133.         //Finish checksum
  134.         checksum = (checksum & 0xffff) + (checksum >> 16);
  135.         checksum = (checksum)+(checksum >> 16);
  136.         checksum = checksum & 0xffff;
  137.  
  138.         checksum += (unsigned long)(filesize);
  139.  
  140.         fclose(fptr);
  141.  
  142.         //Return checksum
  143.         return (uint32_t)checksum;
  144. }
  145.  
  146. bool repair_pe_checksum(LPCTSTR filename) {
  147.         size_t peoffset;
  148.         FILE* fptr;
  149.  
  150.         uint32_t checksum = calculate_checksum(filename);
  151.         //if (checksum == 0x00000000) return false;
  152.  
  153.         fptr = _wfopen(filename, L"rb+");
  154.         if (fptr == NULL) return false;
  155.  
  156.         fseek(fptr, 0x3C, SEEK_SET);
  157.         fread(&peoffset, sizeof(peoffset), 1, fptr);
  158.  
  159.         fseek(fptr, (long)peoffset + 88, SEEK_SET);
  160.         fwrite(&checksum, sizeof(uint32_t), 1, fptr);
  161.  
  162.         fclose(fptr);
  163.  
  164.         return true;
  165. }
  166.  
  167. bool removeFromFile(LPCTSTR pluginfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
  168.         bool bSuccessful = false;
  169.  
  170.         HANDLE hRes = BeginUpdateResource(pluginfile, false);
  171.         if (hRes != NULL) {
  172.                 if (UpdateResource(hRes, lpType, lpName, wLanguage, NULL, 0)) {
  173.                         if (EndUpdateResource(hRes, false)) {
  174.                                 bSuccessful = true;
  175.                         }
  176.                 }
  177.                 else {
  178.                         EndUpdateResource(hRes, true);
  179.                 }
  180.         }
  181.  
  182.         return bSuccessful;
  183. }
  184.  
  185. bool addToFile(LPCTSTR pluginfile, LPCTSTR otherfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
  186.         HANDLE hFile;
  187.         DWORD dwFileSize, dwBytesRead;
  188.         LPBYTE lpBuffer;
  189.         bool bSuccessful = false;
  190.  
  191.         hFile = CreateFile(otherfile, GENERIC_READ,
  192.                 0,
  193.                 NULL,
  194.                 OPEN_EXISTING,
  195.                 FILE_ATTRIBUTE_NORMAL,
  196.                 NULL);
  197.  
  198.         if (INVALID_HANDLE_VALUE != hFile)
  199.         {
  200.                 dwFileSize = GetFileSize(hFile, NULL);
  201.  
  202.                 //lpBuffer = new BYTE[dwFileSize];
  203.                 lpBuffer = (LPBYTE)malloc(dwFileSize);
  204.  
  205.                 if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
  206.                 {
  207.                         HANDLE hRes = BeginUpdateResource(pluginfile, false);
  208.                         if (hRes != NULL) {
  209.                                 if (UpdateResource(hRes, lpType, lpName, wLanguage, lpBuffer, dwFileSize)) {
  210.                                         if (EndUpdateResource(hRes, false)) {
  211.                                                 bSuccessful = true;
  212.                                         }
  213.                                 }
  214.                                 else {
  215.                                         EndUpdateResource(hRes, true);
  216.                                 }
  217.                         }
  218.                 }
  219.  
  220.                 //delete[] lpBuffer;
  221.                 free(lpBuffer);
  222.  
  223.                 CloseHandle(hFile);
  224.         }
  225.  
  226.         return bSuccessful;
  227. }
  228.  
  229. int main()
  230. {
  231.         LPCTSTR lpType = L"TPLT";
  232.         LPCTSTR lpName32 = (LPCTSTR)1032;
  233.         LPCTSTR lpName64 = (LPCTSTR)1064;
  234.         WORD wLanguage = 1033; // en-US
  235.  
  236.         LPCTSTR file32in = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\in\\FilterFoundry.8bf";
  237.         LPCTSTR file64in = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\in\\FilterFoundry64.8bf";
  238.         LPCTSTR file32out = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\out\\FilterFoundry.8bf";
  239.         LPCTSTR file64out = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\out\\FilterFoundry64.8bf";
  240.         LPCTSTR file32tmp = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\FilterFoundry.tmp";
  241.         LPCTSTR file64tmp = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\FilterFoundry64.tmp";
  242.  
  243.         // 1. Copy "IN" to "TMP"
  244.  
  245.         if (!CopyFile(file32in, file32tmp, false)) {
  246.                 DeleteFile(file32out);
  247.                 DeleteFile(file64out);
  248.                 printf("Error: Copyfile 32in > 32tmp\n");
  249.                 return 1;
  250.         }
  251.  
  252.         if (!CopyFile(file64in, file64tmp, false)) {
  253.                 DeleteFile(file32out);
  254.                 DeleteFile(file64out);
  255.                 printf("Error: Copyfile 64in > 64tmp\n");
  256.                 return 1;
  257.         }
  258.  
  259.         // 2. Remove any 32/64 residue in "TMP"
  260.  
  261.         removeFromFile(file32tmp, lpType, lpName32, wLanguage);
  262.         removeFromFile(file32tmp, lpType, lpName64, wLanguage);
  263.         removeFromFile(file64tmp, lpType, lpName32, wLanguage);
  264.         removeFromFile(file64tmp, lpType, lpName64, wLanguage);
  265.  
  266.         // 3. Update timestamp
  267.  
  268.         if (!update_pe_timestamp(file32tmp, time(0))) {
  269.                 DeleteFile(file32out);
  270.                 DeleteFile(file64out);
  271.                 printf("Error: Update TMP timestamp 32\n");
  272.                 return 1;
  273.         }
  274.  
  275.         if (!update_pe_timestamp(file64tmp, time(0))) {
  276.                 DeleteFile(file32out);
  277.                 DeleteFile(file64out);
  278.                 printf("Error: Update TMP timestamp 64\n");
  279.                 return 1;
  280.         }
  281.  
  282.         // 4. Repair checksums
  283.  
  284.         if (!repair_pe_checksum(file32tmp)) {
  285.                 DeleteFile(file32out);
  286.                 DeleteFile(file64out);
  287.                 printf("Error: Repair TMP checksum 32\n");
  288.                 return 1;
  289.         }
  290.         if (!repair_pe_checksum(file64tmp)) {
  291.                 DeleteFile(file32out);
  292.                 DeleteFile(file64out);
  293.                 printf("Error: Repair TMP checksum 64\n");
  294.                 return 1;
  295.         }
  296.  
  297.         // 5. Copy "TMP" to "OUT" (will be edited later)
  298.  
  299.         if (!CopyFile(file32tmp, file32out, false)) {
  300.                 DeleteFile(file32out);
  301.                 DeleteFile(file64out);
  302.                 printf("Error: Copyfile 32tmp > 32out\n");
  303.                 return 1;
  304.         }
  305.         if (!CopyFile(file64tmp, file64out, false)) {
  306.                 DeleteFile(file32out);
  307.                 DeleteFile(file64out);
  308.                 printf("Error: Copyfile 64tmp > 64out\n");
  309.                 return 1;
  310.         }
  311.  
  312.         // 6. Add 32/64 "TMP" to 64/32 "OUT"
  313.  
  314.         if (!addToFile(file32out, file32tmp, lpType, lpName32, wLanguage)) {
  315.                 DeleteFile(file32out);
  316.                 DeleteFile(file64out);
  317.                 printf("Error: Add 32 to 32\n");
  318.                 return 1;
  319.         }
  320.         if (!addToFile(file32out, file64tmp, lpType, lpName64, wLanguage)) {
  321.                 DeleteFile(file32out);
  322.                 DeleteFile(file64out);
  323.                 printf("Error: Add 64 to 32\n");
  324.                 return 1;
  325.         }
  326.  
  327.         if (!addToFile(file64out, file32tmp, lpType, lpName32, wLanguage)) {
  328.                 DeleteFile(file32out);
  329.                 DeleteFile(file64out);
  330.                 printf("Error: Add 32 to 64\n");
  331.                 return 1;
  332.         }
  333.  
  334.         if (!addToFile(file64out, file64tmp, lpType, lpName64, wLanguage)) {
  335.                 DeleteFile(file32out);
  336.                 DeleteFile(file64out);
  337.                 printf("Error: Add 64 to 64\n");
  338.                 return 1;
  339.         }
  340.  
  341.         // 7. Delete "TMP"
  342.  
  343.         DeleteFile(file32tmp);
  344.         DeleteFile(file64tmp);
  345.  
  346.         // 8. Update timestamp
  347.  
  348.         if (!update_pe_timestamp(file32out, time(0))) {
  349.                 DeleteFile(file32out);
  350.                 DeleteFile(file64out);
  351.                 printf("Error: Update OUT timestamp 32\n");
  352.                 return 1;
  353.         }
  354.  
  355.         if (!update_pe_timestamp(file64out, time(0))) {
  356.                 DeleteFile(file32out);
  357.                 DeleteFile(file64out);
  358.                 printf("Error: Update OUT timestamp 64\n");
  359.                 return 1;
  360.         }
  361.  
  362.         // 9. Repair checksums
  363.  
  364.         if (!repair_pe_checksum(file32out)) {
  365.                 DeleteFile(file32out);
  366.                 DeleteFile(file64out);
  367.                 printf("Error: Repair OUT checksum 32\n");
  368.                 return 1;
  369.         }
  370.         if (!repair_pe_checksum(file64out)) {
  371.                 DeleteFile(file32out);
  372.                 DeleteFile(file64out);
  373.                 printf("Error: Repair OUT checksum 64\n");
  374.                 return 1;
  375.         }
  376.  
  377.         // 10. All done!
  378.  
  379.         printf("All OK!\n");
  380.         return 0;
  381. }
  382.