diff --git a/Source/build.cpp b/Source/build.cpp index 9dec08ee..95245b45 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -2776,32 +2776,33 @@ int CEXEBuild::uninstall_generate() if (add_db_data((char *)m_unicon_data,unicondata_size) < 0) return PS_ERROR; #ifdef NSIS_CONFIG_CRC_SUPPORT - #ifdef NSIS_CONFIG_CRC_ANAL - crc=CRC32(crc,header_data_new,icon_offset); - #else - crc=CRC32(crc,header_data_new+512,icon_offset-512); - #endif - // This bunch of lines do CRC for the uninstaller icon data - unsigned char* seeker = m_unicon_data; - DWORD dwEndOfIcons = 0; - while (*seeker) { - DWORD dwSize = *(DWORD*)seeker; - seeker += sizeof(DWORD); - DWORD dwOffset = *(DWORD*)seeker; - seeker += sizeof(DWORD); - // Do CRC for icon data - crc=CRC32(crc,seeker,dwSize); - seeker += dwSize; - if (*seeker) { - // Do CRC for data between icons - crc=CRC32(crc,header_data_new+dwOffset+dwSize,(*(DWORD*)(seeker+sizeof(DWORD)))-dwOffset-dwSize); - } - else { - dwEndOfIcons = dwOffset+dwSize; + { + // "create" the uninstaller + LPBYTE uninst_header = (LPBYTE) malloc(exeheader_size_new); + if (!uninst_header) + return PS_ERROR; + + memcpy(uninst_header, header_data_new, exeheader_size_new); + + // patch the icons + LPBYTE seeker = m_unicon_data; + while (*seeker) { + DWORD dwSize = *(LPDWORD) seeker; + seeker += sizeof(DWORD); + DWORD dwOffset = *(LPDWORD) seeker; + seeker += sizeof(DWORD); + memcpy(uninst_header + dwOffset, seeker, dwSize); + seeker += dwSize; } + +#ifdef NSIS_CONFIG_CRC_ANAL + crc=CRC32(crc, uninst_header, exeheader_size_new); +#else + crc=CRC32(crc, uninst_header + 512, exeheader_size_new - 512); +#endif + + free(uninst_header); } - // Done with icons, carry on - crc=CRC32(crc,header_data_new+dwEndOfIcons,exeheader_size_new-dwEndOfIcons); #endif fh.nsinst[0]=FH_INT1; fh.nsinst[1]=FH_INT2; diff --git a/Source/util.cpp b/Source/util.cpp index 7d5f9a48..c8341261 100644 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -306,7 +306,7 @@ int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIcon MY_ASSERT((int)rdIcons - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); - unsigned char* seeker = uninstIconData; + MY_ASSERT(rdIcons->Header.NumberOfIdEntries == 0, "no icons found"); for (i = 0; i < rdIcons->Header.NumberOfIdEntries; i++) { // Icons dir can't have named entries MY_ASSERT(!rdIcons->Entries[i].DataIsDirectory, "bad resource directory"); @@ -319,18 +319,38 @@ int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIcon MY_ASSERT((int)rde - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); - DWORD dwSize = *(DWORD*)seeker; - seeker += sizeof(DWORD); - MY_ASSERT(dwSize != rde->Size, "installer, uninstaller icon size mismatch - see the Icon instruction's documentation for more information"); + // find icon to replace + LPBYTE seeker = uninstIconData; + while (*seeker) { + DWORD dwSize = *(DWORD*)seeker; + seeker += sizeof(DWORD); + DWORD dwOffset = *(DWORD*)seeker; + // if we haven't set the offset yet and the size is the same, it's a match + if (!dwOffset && dwSize == rde->Size) + break; + + seeker += dwSize + sizeof(DWORD); + + // reached the end of the list and no match + MY_ASSERT(!*seeker, "installer, uninstaller icon size mismatch - see the Icon instruction's documentation for more information"); + } + // Set offset - *(DWORD*)seeker = rde->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); + *(LPDWORD) seeker = rde->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); MY_ASSERT(*(int*)seeker > iNextSection || *(int*)seeker < (int)rdRoot - (int)exeHeader, "invalid data offset - icon resource probably compressed"); - - seeker += sizeof(DWORD) + dwSize; } - MY_ASSERT(i == 0, "no icons found"); - MY_ASSERT(*(DWORD*)seeker != 0, "number of icons doesn't match"); + + LPBYTE seeker = uninstIconData; + while (*seeker) { + DWORD dwSize = *(DWORD*)seeker; + seeker += sizeof(DWORD); + DWORD dwOffset = *(DWORD*)seeker; + seeker += sizeof(DWORD); + // offset isn't set which means we found no match for this one + MY_ASSERT(!dwOffset, "number of icons doesn't match"); + seeker += dwSize; + } return PIMAGE_RESOURCE_DATA_ENTRY(PRESOURCE_DIRECTORY(rdIcons->Entries[0].OffsetToDirectory + DWORD(rdRoot))->Entries[0].OffsetToData + DWORD(rdRoot))->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); }