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.
704 lines
20 KiB
704 lines
20 KiB
#include <windows.h>
|
|
|
|
#include "crc32.h"
|
|
|
|
#include "chksect.h"
|
|
|
|
#define CHECK_SECTION
|
|
|
|
#ifndef offsetof
|
|
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
|
#endif
|
|
|
|
#define RoundUp(n,scale) (scale * ((n + scale - 1) / scale))
|
|
|
|
#define IsMemZero(pv,cb) (!(*((char *)pv) || memcmp(pv,((char *)pv)+1,cb-1)))
|
|
|
|
#pragma intrinsic(memcpy,memcmp)
|
|
|
|
enum
|
|
{
|
|
EX_CHECKSUM,
|
|
EX_SECURITY,
|
|
EX_CRC32FILE,
|
|
EX_EOF,
|
|
MAX_EXCLUDE
|
|
};
|
|
|
|
#define MAX_BUFFER (256*1024) /* must be even */
|
|
|
|
typedef struct
|
|
{
|
|
DWORD signature;
|
|
DWORD crc32File;
|
|
DWORD cbCabFile;
|
|
} SELFTEST_SECTION;
|
|
|
|
#define SECTION_NAME "Ext_Cab1"
|
|
|
|
#define SECTION_SIGNATURE (0x4D584653)
|
|
|
|
|
|
#ifdef ADD_SECTION
|
|
SELFTEST_RESULT AddSection(char *pszEXEFileName,char *pszCABFileName)
|
|
#else
|
|
#ifdef CHECK_SECTION
|
|
SELFTEST_RESULT CheckSection(char *pszEXEFileName)
|
|
#else
|
|
SELFTEST_RESULT SelfTest(char *pszEXEFileName,
|
|
unsigned long *poffCabinet,unsigned long *pcbCabinet)
|
|
#endif
|
|
#endif
|
|
{
|
|
HANDLE hFile; // handle to the file we're updating
|
|
enum SELFTEST_RESULT result; // our return code
|
|
union
|
|
{
|
|
IMAGE_DOS_HEADER dos;
|
|
IMAGE_NT_HEADERS nt;
|
|
IMAGE_SECTION_HEADER section;
|
|
} header; // used to examine the file
|
|
DWORD offNTHeader; // file offset to NT header
|
|
int cSections; // number of sections in the file
|
|
unsigned char *pBuffer; // general-purpose buffer
|
|
DWORD cbActual; // # of bytes actual read/written
|
|
#ifndef CHECK_SECTION
|
|
unsigned long crc32; // computed CRC-32
|
|
struct
|
|
{
|
|
DWORD offExclude;
|
|
DWORD cbExclude;
|
|
} excludeList[MAX_EXCLUDE]; // list of ranges to exclude from CRC
|
|
int iExclude; // exclude list index
|
|
DWORD offSelfTestSection; // file offset of our added section
|
|
SELFTEST_SECTION SelfTestSection; // added section header
|
|
DWORD cbFile; // number of bytes in file/region
|
|
DWORD cbChunk; // number of bytes in current chunk
|
|
DWORD offFile; // current file offset
|
|
#endif
|
|
#ifdef ADD_SECTION
|
|
DWORD offSectionHeader; // file offset of section header
|
|
DWORD offMaxVirtualAddress; // lowest unused virtual address
|
|
DWORD cbAlignVirtual; // virtual address alignment increment
|
|
DWORD cbAlignFile; // file address alignment increment
|
|
HANDLE hCABFile; // cabinet file handle
|
|
DWORD cbCABFile; // cabinet file size
|
|
DWORD checksum; // generated checksum
|
|
WORD *pBufferW; // used to generate checksum
|
|
#endif
|
|
#ifdef CHECK_SECTION
|
|
DWORD offSectionHeaderEnd; // first unused byte after section headers
|
|
DWORD offFirstSection; // first used byte after that
|
|
DWORD offImportStart; // where the import entries start
|
|
DWORD cbImport; // size of import entry data
|
|
#endif
|
|
|
|
#ifndef CHECK_SECTION
|
|
GenerateCRC32Table();
|
|
#endif
|
|
|
|
pBuffer = (void *) GlobalAlloc(GMEM_FIXED,MAX_BUFFER);
|
|
if (pBuffer == NULL)
|
|
{
|
|
result = SELFTEST_NO_MEMORY;
|
|
goto done_no_buffer;
|
|
}
|
|
|
|
#ifdef ADD_SECTION
|
|
/* get size of cabinet */
|
|
|
|
hCABFile = CreateFile(pszCABFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
|
|
OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
if (hCABFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
result = SELFTEST_FILE_NOT_FOUND;
|
|
goto done_no_cab;
|
|
}
|
|
|
|
cbCABFile = GetFileSize(hCABFile,NULL);
|
|
#endif
|
|
|
|
|
|
/* open EXE image */
|
|
|
|
#ifdef ADD_SECTION
|
|
hFile = CreateFile(pszEXEFileName,GENERIC_READ|GENERIC_WRITE,0,NULL,
|
|
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
#else
|
|
hFile = CreateFile(pszEXEFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
|
|
OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
#endif
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
result = SELFTEST_FILE_NOT_FOUND;
|
|
goto done_no_exe;
|
|
}
|
|
|
|
|
|
/* read MS-DOS header */
|
|
|
|
if ((ReadFile(hFile,&header.dos,sizeof(IMAGE_DOS_HEADER),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_DOS_HEADER)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if (header.dos.e_magic != IMAGE_DOS_SIGNATURE)
|
|
{
|
|
offNTHeader = 0;
|
|
}
|
|
else
|
|
{
|
|
offNTHeader = header.dos.e_lfanew;
|
|
}
|
|
|
|
|
|
/* read PE header */
|
|
|
|
SetFilePointer(hFile,offNTHeader,NULL,FILE_BEGIN);
|
|
|
|
if ((ReadFile(hFile,&header.nt,sizeof(IMAGE_NT_HEADERS),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_NT_HEADERS)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if (header.nt.Signature != IMAGE_NT_SIGNATURE)
|
|
{
|
|
result = SELFTEST_NOT_PE_FILE;
|
|
goto done;
|
|
}
|
|
|
|
cSections = header.nt.FileHeader.NumberOfSections;
|
|
|
|
#ifdef ADD_SECTION
|
|
cbAlignVirtual = header.nt.OptionalHeader.SectionAlignment;
|
|
cbAlignFile = header.nt.OptionalHeader.FileAlignment;
|
|
offMaxVirtualAddress = 0;
|
|
#endif
|
|
|
|
|
|
#ifndef CHECK_SECTION
|
|
/* determine current file size */
|
|
|
|
cbFile = GetFileSize(hFile,NULL);
|
|
if (cbFile == 0xFFFFFFFF)
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
#endif
|
|
|
|
#ifndef CHECK_SECTION
|
|
/* see if we've been signed */
|
|
|
|
if (header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress != 0)
|
|
{
|
|
#ifdef ADD_SECTION
|
|
result = SELFTEST_SIGNED;
|
|
goto done;
|
|
#else
|
|
/* make sure certificate is at the end of the file */
|
|
|
|
if (cbFile !=
|
|
(header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress
|
|
+ header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size))
|
|
{
|
|
result = SELFTEST_FAILED;
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
/* ignore anything starting at the certificate */
|
|
|
|
cbFile = header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef ADD_SECTION
|
|
/* determine lowest un-used virtual address */
|
|
#else
|
|
/* locate our added section */
|
|
#endif
|
|
|
|
#ifndef CHECK_SECTION
|
|
offSelfTestSection = 0;
|
|
#endif
|
|
|
|
#ifdef ADD_SECTION
|
|
offSectionHeader = offNTHeader +
|
|
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
|
|
header.nt.FileHeader.SizeOfOptionalHeader +
|
|
cSections * sizeof(IMAGE_SECTION_HEADER);
|
|
#endif
|
|
|
|
SetFilePointer(hFile,(offNTHeader + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
|
|
header.nt.FileHeader.SizeOfOptionalHeader),NULL,FILE_BEGIN);
|
|
|
|
#ifdef CHECK_SECTION
|
|
offSectionHeaderEnd = offNTHeader +
|
|
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
|
|
header.nt.FileHeader.SizeOfOptionalHeader +
|
|
cSections * sizeof(IMAGE_SECTION_HEADER);
|
|
|
|
offImportStart = header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
|
|
cbImport = header.nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size;
|
|
|
|
if ((ReadFile(hFile,&header.section,sizeof(IMAGE_SECTION_HEADER),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_SECTION_HEADER)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
offFirstSection = header.section.PointerToRawData;
|
|
|
|
if ((offFirstSection - offSectionHeaderEnd) > 0)
|
|
{
|
|
SetFilePointer(hFile,offSectionHeaderEnd,NULL,FILE_BEGIN);
|
|
|
|
if ((ReadFile(hFile,pBuffer,(offFirstSection - offSectionHeaderEnd),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != (DWORD) (offFirstSection - offSectionHeaderEnd)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if ((offImportStart >= offSectionHeaderEnd) &&
|
|
((offImportStart + cbImport) <= offFirstSection))
|
|
{
|
|
memset(pBuffer + (offImportStart - offSectionHeaderEnd),0,cbImport);
|
|
}
|
|
|
|
if ((*pBuffer != '\0') ||
|
|
(((offFirstSection - offSectionHeaderEnd) > 1) &&
|
|
(memcmp(pBuffer,pBuffer + 1,(offFirstSection - offSectionHeaderEnd - 1)) != 0)))
|
|
{
|
|
result = SELFTEST_DIRTY;
|
|
}
|
|
else
|
|
{
|
|
result = SELFTEST_NO_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = SELFTEST_NO_ERROR;
|
|
}
|
|
#else
|
|
while (cSections--)
|
|
{
|
|
if ((ReadFile(hFile,&header.section,sizeof(IMAGE_SECTION_HEADER),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_SECTION_HEADER)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if (!memcmp(header.section.Name,SECTION_NAME,sizeof(header.section.Name)))
|
|
{
|
|
/* found our added section */
|
|
|
|
#ifdef ADD_SECTION
|
|
result = SELFTEST_ALREADY;
|
|
goto done;
|
|
#else
|
|
offSelfTestSection = header.section.PointerToRawData;
|
|
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
#ifdef ADD_SECTION
|
|
if (offMaxVirtualAddress <
|
|
(header.section.VirtualAddress + header.section.Misc.VirtualSize))
|
|
{
|
|
offMaxVirtualAddress =
|
|
(header.section.VirtualAddress + header.section.Misc.VirtualSize);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef ADD_SECTION
|
|
/* increase number of sections in the file; whack checksum */
|
|
|
|
SetFilePointer(hFile,offNTHeader,NULL,FILE_BEGIN);
|
|
|
|
if ((ReadFile(hFile,&header.nt,sizeof(IMAGE_NT_HEADERS),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_NT_HEADERS)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
header.nt.FileHeader.NumberOfSections++;
|
|
header.nt.OptionalHeader.CheckSum = 0;
|
|
header.nt.OptionalHeader.SizeOfImage =
|
|
RoundUp(offMaxVirtualAddress,cbAlignVirtual) +
|
|
RoundUp((sizeof(SELFTEST_SECTION) + cbCABFile),cbAlignVirtual);
|
|
|
|
SetFilePointer(hFile,offNTHeader,NULL,FILE_BEGIN);
|
|
|
|
if ((WriteFile(hFile,&header.nt,sizeof(IMAGE_NT_HEADERS),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_NT_HEADERS)))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* make sure there's room for another section header */
|
|
|
|
SetFilePointer(hFile,offSectionHeader,NULL,FILE_BEGIN);
|
|
|
|
if ((ReadFile(hFile,&header.section,sizeof(IMAGE_SECTION_HEADER),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_SECTION_HEADER)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if (!IsMemZero(&header.section,sizeof(IMAGE_SECTION_HEADER)))
|
|
{
|
|
result = SELFTEST_NO_SECTION;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* create the new section header */
|
|
|
|
memcpy(header.section.Name,SECTION_NAME,sizeof(header.section.Name));
|
|
header.section.SizeOfRawData =
|
|
RoundUp((sizeof(SELFTEST_SECTION) + cbCABFile),cbAlignFile);
|
|
header.section.PointerToRawData =
|
|
RoundUp(cbFile,cbAlignFile);
|
|
header.section.VirtualAddress =
|
|
RoundUp(offMaxVirtualAddress,cbAlignVirtual);
|
|
header.section.Misc.VirtualSize =
|
|
RoundUp((sizeof(SELFTEST_SECTION) + cbCABFile),cbAlignVirtual);
|
|
header.section.Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
|
|
IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ);
|
|
|
|
|
|
/* write the new section header */
|
|
|
|
SetFilePointer(hFile,offSectionHeader,NULL,FILE_BEGIN);
|
|
|
|
if ((WriteFile(hFile,&header.section,sizeof(IMAGE_SECTION_HEADER),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(IMAGE_SECTION_HEADER)))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* create the new section data */
|
|
|
|
memset(&SelfTestSection,0,sizeof(SelfTestSection));
|
|
SelfTestSection.signature = SECTION_SIGNATURE;
|
|
SelfTestSection.cbCabFile = cbCABFile;
|
|
|
|
offSelfTestSection = header.section.PointerToRawData;
|
|
|
|
SetFilePointer(hFile,offSelfTestSection,NULL,FILE_BEGIN);
|
|
|
|
if ((WriteFile(hFile,&SelfTestSection,sizeof(SelfTestSection),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(SelfTestSection)))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* copy cabinet into section */
|
|
|
|
SetFilePointer(hCABFile,0,NULL,FILE_BEGIN);
|
|
|
|
cbFile = cbCABFile;
|
|
|
|
while (cbFile)
|
|
{
|
|
if (cbFile > MAX_BUFFER)
|
|
{
|
|
cbChunk = MAX_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
cbChunk = cbFile;
|
|
}
|
|
|
|
if ((ReadFile(hCABFile,pBuffer,cbChunk,&cbActual,NULL) != TRUE)
|
|
|| (cbActual != cbChunk))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
if ((WriteFile(hFile,pBuffer,cbChunk,&cbActual,NULL) != TRUE)
|
|
|| (cbActual != cbChunk))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
}
|
|
|
|
cbFile -= cbChunk;
|
|
}
|
|
|
|
|
|
/* pad added section as needed */
|
|
|
|
cbChunk = header.section.SizeOfRawData - sizeof(SelfTestSection) - cbCABFile;
|
|
|
|
if (cbChunk != 0)
|
|
{
|
|
memset(pBuffer,0,cbChunk);
|
|
|
|
if ((WriteFile(hFile,pBuffer,cbChunk,&cbActual,NULL) != TRUE)
|
|
|| (cbActual != cbChunk))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
/* we've now increased total size of the file */
|
|
|
|
cbFile = offSelfTestSection + header.section.SizeOfRawData;
|
|
#else
|
|
|
|
/* make sure our added section was found */
|
|
|
|
if (offSelfTestSection == 0)
|
|
{
|
|
result = SELFTEST_NO_SECTION;
|
|
goto done;
|
|
}
|
|
#endif
|
|
|
|
/* If this EXE gets signed, the checksum will be changed. */
|
|
|
|
excludeList[EX_CHECKSUM].offExclude = offNTHeader +
|
|
offsetof(IMAGE_NT_HEADERS,OptionalHeader.CheckSum);
|
|
excludeList[EX_CHECKSUM].cbExclude =
|
|
sizeof(header.nt.OptionalHeader.CheckSum);
|
|
|
|
|
|
/* If this EXE gets signed, the security entry will be changed. */
|
|
|
|
excludeList[EX_SECURITY].offExclude = offNTHeader +
|
|
offsetof(IMAGE_NT_HEADERS,
|
|
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
|
|
excludeList[EX_SECURITY].cbExclude = sizeof(IMAGE_DATA_DIRECTORY);
|
|
|
|
|
|
/* Can't CRC our own CRC field. */
|
|
|
|
excludeList[EX_CRC32FILE].offExclude = offSelfTestSection +
|
|
offsetof(SELFTEST_SECTION,crc32File);
|
|
excludeList[EX_CRC32FILE].cbExclude = sizeof(SelfTestSection.crc32File);
|
|
|
|
|
|
/* Stop at end of known file. */
|
|
|
|
/* Note: current code assumes that the only thing which could */
|
|
/* be appended to the file after this is the certificate from */
|
|
/* codesigning, and that it will be pointed at by the security */
|
|
/* entry. If anything else appends, or padding is added before */
|
|
/* the certificate, we'll have to store this file size in the */
|
|
/* added section, and retrieve it before running the CRC. */
|
|
|
|
excludeList[EX_EOF].offExclude = cbFile;
|
|
|
|
|
|
/* Compute the CRC-32 of the file, skipping excluded extents. */
|
|
/* This code assumes excludeList is sorted by offExclude. */
|
|
|
|
crc32 = CRC32_INITIAL_VALUE;
|
|
offFile = 0;
|
|
|
|
#ifdef ADD_SECTION
|
|
/* Along the way, compute the correct checksum for this new */
|
|
/* image. We know that each of the sections on the exclude */
|
|
/* list just happened to be zeroed right now, so they won't */
|
|
/* affect our checksum. But we will have to add our new CRC32 */
|
|
/* value to the checksum, because it will be in the file when */
|
|
/* we're done. It helps that we know that all the exclusions */
|
|
/* on the list are WORD aligned and have even lengths. */
|
|
|
|
/* The checksum in a PE file is a 16-bit sum of 16-bit words */
|
|
/* in the file, with wrap-around carry, while the checksum */
|
|
/* field is filled with zero. The file's length is added, */
|
|
/* yielding a 32-bit result. */
|
|
|
|
checksum = 0;
|
|
#endif
|
|
|
|
for (iExclude = 0; iExclude < MAX_EXCLUDE; iExclude++)
|
|
{
|
|
SetFilePointer(hFile,offFile,NULL,FILE_BEGIN);
|
|
|
|
cbFile = excludeList[iExclude].offExclude - offFile;
|
|
|
|
while (cbFile)
|
|
{
|
|
if (cbFile > MAX_BUFFER)
|
|
{
|
|
cbChunk = MAX_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
cbChunk = cbFile;
|
|
}
|
|
|
|
if ((ReadFile(hFile,pBuffer,cbChunk,&cbActual,NULL) != TRUE)
|
|
|| (cbActual != cbChunk))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
CRC32Update(&crc32,pBuffer,cbChunk);
|
|
|
|
offFile += cbChunk;
|
|
cbFile -= cbChunk;
|
|
|
|
#ifdef ADD_SECTION
|
|
/* roll buffer into checksum */
|
|
|
|
pBufferW = (WORD *) pBuffer;
|
|
|
|
cbChunk >>= 1;
|
|
|
|
while (cbChunk--)
|
|
{
|
|
checksum += *pBufferW++;
|
|
|
|
if (checksum > 0x0000FFFF)
|
|
{
|
|
checksum -= 0x0000FFFF;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* INSERT PROGRESS GAUGE HERE:
|
|
* %complete = (offFile * 100.0) / excludeList[EX_EOF].offExclude
|
|
*/
|
|
}
|
|
|
|
offFile += excludeList[iExclude].cbExclude;
|
|
}
|
|
|
|
|
|
#ifdef ADD_SECTION
|
|
/* account for CRC32 value in checksum */
|
|
|
|
checksum += (WORD) crc32;
|
|
checksum += (crc32 >> 16);
|
|
|
|
while (checksum > 0x0000FFFF)
|
|
{
|
|
checksum -= 0x0000FFFF;
|
|
}
|
|
|
|
|
|
/* add file length to checksum */
|
|
|
|
checksum += excludeList[EX_EOF].offExclude;
|
|
|
|
|
|
/* update CRC-32 value in added section */
|
|
|
|
SetFilePointer(hFile,excludeList[EX_CRC32FILE].offExclude,NULL,FILE_BEGIN);
|
|
|
|
if ((WriteFile(hFile,&crc32,sizeof(crc32),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(crc32)))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* update checksum value in header */
|
|
|
|
SetFilePointer(hFile,excludeList[EX_CHECKSUM].offExclude,NULL,FILE_BEGIN);
|
|
|
|
if ((WriteFile(hFile,&checksum,sizeof(checksum),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(checksum)))
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* done */
|
|
|
|
if (CloseHandle(hFile) != TRUE)
|
|
{
|
|
result = SELFTEST_WRITE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
result = SELFTEST_NO_ERROR;
|
|
}
|
|
|
|
goto done_no_exe;
|
|
#else
|
|
/* read the header from the added section */
|
|
|
|
SetFilePointer(hFile,offSelfTestSection,NULL,FILE_BEGIN);
|
|
|
|
if ((ReadFile(hFile,&SelfTestSection,sizeof(SelfTestSection),&cbActual,NULL) != TRUE)
|
|
|| (cbActual != sizeof(SelfTestSection)))
|
|
{
|
|
result = SELFTEST_READ_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
|
|
/* verify CRC-32 value in added section */
|
|
|
|
if ((SelfTestSection.signature != SECTION_SIGNATURE) ||
|
|
(crc32 != SelfTestSection.crc32File))
|
|
{
|
|
result = SELFTEST_FAILED;
|
|
}
|
|
else
|
|
{
|
|
*poffCabinet = offSelfTestSection + sizeof(SelfTestSection);
|
|
*pcbCabinet = SelfTestSection.cbCabFile;
|
|
|
|
result = SELFTEST_NO_ERROR;
|
|
}
|
|
#endif
|
|
#endif // CHECK_SECTION
|
|
|
|
done:
|
|
CloseHandle(hFile);
|
|
|
|
done_no_exe:
|
|
|
|
#ifdef ADD_SECTION
|
|
CloseHandle(hCABFile);
|
|
|
|
done_no_cab:
|
|
#endif
|
|
|
|
GlobalFree((HGLOBAL) pBuffer);
|
|
|
|
done_no_buffer:
|
|
|
|
#ifdef ADD_SECTION
|
|
/* destroy failed attempt */
|
|
|
|
if (result != SELFTEST_NO_ERROR)
|
|
{
|
|
DeleteFile(pszEXEFileName);
|
|
}
|
|
#endif
|
|
|
|
return(result);
|
|
}
|