compressdlg.cpp

来自「一些初级的网络编程」· C++ 代码 · 共 1,352 行 · 第 1/3 页

CPP
1,352
字号
		dwSecStart += sizeof(IMAGE_SECTION_HEADER);
		dwBackupSecStart += sizeof(IMAGE_SECTION_HEADER);
	}

	// Something strange in release mode ?!?!?!?
	// need to track this down really, but for now, just make sure
	// we reset the first sections PointerToRawData
	{
		dwSecStart = (DWORD)pNtHdr;
		dwSecStart += 24;
		dwSecStart += wSizeO;

		dwBackupSecStart = (DWORD)pBackupNtHdr;
		dwBackupSecStart += 24;
		dwBackupSecStart += wBackupSizeO;

		pSecHdr = (PIMAGE_SECTION_HEADER)dwSecStart;
		pBackupSecHdr = (PIMAGE_SECTION_HEADER)dwBackupSecStart;

		pSecHdr->PointerToRawData = pBackupSecHdr->PointerToRawData;
	}

	//m_ProgressCtrl.SetPos(100);
}

LPVOID CCompressDlg::Compress(LPVOID lpInputBuffer, DWORD dwInputSize, DWORD* dwOutputSize, PFNAPLIBCALLBACK pfnCallback)
{
	// For aPlib
	BYTE* pWorkmem = 0;
	BYTE* pPacked = 0;

	pWorkmem = (BYTE*)malloc(aP_workmem_size(dwInputSize));
	pPacked = (BYTE*)malloc(aP_max_packed_size(dwInputSize));

	*dwOutputSize = aP_pack(lpInputBuffer, pPacked, dwInputSize, pWorkmem, pfnCallback, this);
	
	return pPacked;
}

LPVOID CCompressDlg::BuildNewResourceSection(LPVOID lpMapping, DWORD* dwOutputSize)
{
	PIMAGE_DOS_HEADER pDosHdr = 0;
	PIMAGE_NT_HEADERS pNtHdr = 0;
	PIMAGE_SECTION_HEADER pSecHdr = 0;
	DWORD dwSecStart = 0;
	DWORD dwKatSup = 0;
	LONG lJmp = 0;
	WORD wNumSections = 0;
	WORD wSizeO = 0;
	int i = 0;
	int j = 0;
	int k = 0;

	pDosHdr = (PIMAGE_DOS_HEADER) lpMapping;
	lJmp = pDosHdr->e_lfanew;
	dwKatSup = (DWORD)pDosHdr;
	dwKatSup += lJmp;

	pNtHdr = (PIMAGE_NT_HEADERS)dwKatSup;

	wNumSections = pNtHdr->FileHeader.NumberOfSections;
	wSizeO = pNtHdr->FileHeader.SizeOfOptionalHeader;

	dwSecStart = (DWORD)pNtHdr;
	dwSecStart += 24;
	dwSecStart += wSizeO;

	bool bResource = false;
	PIMAGE_RESOURCE_DIRECTORY pRootDirectory = 0;
	PIMAGE_RESOURCE_DIRECTORY pSubDirectory = 0;
	PIMAGE_RESOURCE_DIRECTORY pSubSubDirectory = 0;
	PIMAGE_RESOURCE_DIRECTORY_ENTRY pEntry = 0;
	PIMAGE_RESOURCE_DIRECTORY_ENTRY pSubEntry = 0;
	PIMAGE_RESOURCE_DIRECTORY_ENTRY pSubSubEntry = 0;
	PIMAGE_RESOURCE_DATA_ENTRY pDataEntry = 0;

	PIMAGE_RESOURCE_DIR_STRING_U pName = 0;

	#pragma pack( push )
	#pragma pack( 2 )
	typedef struct
	{
	   BYTE   bWidth;               // Width, in pixels, of the image
	   BYTE   bHeight;              // Height, in pixels, of the image
	   BYTE   bColorCount;          // Number of colors in image (0 if >=8bpp)
	   BYTE   bReserved;            // Reserved
	   WORD   wPlanes;              // Color Planes
	   WORD   wBitCount;            // Bits per pixel
	   DWORD   dwBytesInRes;         // how many bytes in this resource?
	   WORD   nID;                  // the ID
	} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;

	typedef struct 
	{
	   WORD            idReserved;   // Reserved (must be 0)
	   WORD            idType;       // Resource type (1 for icons)
	   WORD            idCount;      // How many images?
	   GRPICONDIRENTRY   idEntries[1]; // The entries for each image
	} GRPICONDIR, *LPGRPICONDIR;
	#pragma pack( pop )

	LPGRPICONDIR lpGroupIconDir = 0;

	for(i = 0; i < wNumSections; i++)
	{
		pSecHdr = (PIMAGE_SECTION_HEADER)dwSecStart;

		if(strcmp((char*)pSecHdr->Name, ".rsrc") == 0)
		{
			bResource = true;
			break;
		}

		// move to next section header
		dwSecStart += sizeof(IMAGE_SECTION_HEADER);
	}

	DWORD dwDirectorySize = 0;
	DWORD dwIconSize = 0;
	DWORD dwGroupIconSize = 0;
	DWORD dwVersionSize = 0;
	DWORD dwManifestSize = 0;

	DWORD dwIconCount = 0;
	DWORD dwGroupIconCount = 0;

	if(bResource)
	{
		pRootDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)lpMapping + pSecHdr->PointerToRawData);

		int nDirectoryCount = pRootDirectory->NumberOfIdEntries + pRootDirectory->NumberOfNamedEntries;

		pEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pRootDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

		// First pass - figure out number of icons in first icon group
		for(i = 0; i < nDirectoryCount; i++)
		{
			if(pEntry->DataIsDirectory)
			{
				pSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pEntry->OffsetToDirectory + (DWORD)pRootDirectory);

				int nSubDirectoryCount = pSubDirectory->NumberOfIdEntries + pSubDirectory->NumberOfNamedEntries;

				pSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

				for(j = 0; j < nSubDirectoryCount; j++)
				{
					if(pSubEntry->DataIsDirectory)
					{

						pSubSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pSubEntry->OffsetToDirectory + (DWORD)pRootDirectory);

						int nSubSubDirectoryCount = pSubSubDirectory->NumberOfIdEntries + pSubSubDirectory->NumberOfNamedEntries;

						pSubSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

						for(k = 0; k < nSubSubDirectoryCount; k++)
						{
							if(!pSubSubEntry->DataIsDirectory)
							{
								if(!(pSubSubEntry->OffsetToData & 0x8000000))
								{
									pDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pRootDirectory + pSubSubEntry->OffsetToData);

									switch(pEntry->Name)
									{
									case RT_GROUP_ICON:
										lpGroupIconDir = (LPGRPICONDIR)(RVAToOffset(pDataEntry->OffsetToData, lpMapping) + (DWORD)lpMapping);
										gev.dwFirstGroupIconCount = lpGroupIconDir->idCount;
										break;
									}
								}
							}

							if(lpGroupIconDir)
								break;

							pSubSubEntry++;
						}
					}

					if(lpGroupIconDir)
						break;

					pSubEntry++;
				}
			}

			if(lpGroupIconDir)
				break;

			pEntry++;
		}

		pRootDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)lpMapping + pSecHdr->PointerToRawData);

		nDirectoryCount = pRootDirectory->NumberOfIdEntries + pRootDirectory->NumberOfNamedEntries;

		pEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pRootDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

		// Second pass
		for(i = 0; i < nDirectoryCount; i++)
		{
			if(pEntry->DataIsDirectory)
			{
				pSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pEntry->OffsetToDirectory + (DWORD)pRootDirectory);

				int nSubDirectoryCount = pSubDirectory->NumberOfIdEntries + pSubDirectory->NumberOfNamedEntries;

				pSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

				for(j = 0; j < nSubDirectoryCount; j++)
				{
					if(pSubEntry->DataIsDirectory)
					{

						pSubSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pSubEntry->OffsetToDirectory + (DWORD)pRootDirectory);

						int nSubSubDirectoryCount = pSubSubDirectory->NumberOfIdEntries + pSubSubDirectory->NumberOfNamedEntries;

						pSubSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

						for(k = 0; k < nSubSubDirectoryCount; k++)
						{
							if(!pSubSubEntry->DataIsDirectory)
							{
								if(!(pSubSubEntry->OffsetToData & 0x8000000))
								{
									pDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pRootDirectory + pSubSubEntry->OffsetToData);

									switch(pEntry->Name)
									{
									case RT_ICON:
										// Copy however many icons are in the first icon group
										if(dwIconCount < lpGroupIconDir->idCount)
										{
											dwIconSize += pDataEntry->Size;
											dwIconCount++;
										}
										break;
									case RT_GROUP_ICON:
										// Only copy the first icon group
										if(dwGroupIconCount < 1)
										{
											dwGroupIconSize += pDataEntry->Size;
											dwGroupIconCount++;
										}
										break;
									case RT_VERSION:
										dwVersionSize += pDataEntry->Size;
										break;
									case 24:	// RT_MANIFEST
										dwManifestSize += pDataEntry->Size;
										break;
									}
								}
							}

							dwDirectorySize = pSubSubEntry->OffsetToData + sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY);

							pSubSubEntry++;
						}
					}

					pSubEntry++;
				}
			}
			pEntry++;
		}

		// allocate size of original, will be more than enough for uncompressed resource
		dwDirectorySize = ValidAlignment(dwDirectorySize, 0x200);

		// Reset some counters
		dwIconCount = 0;
		dwGroupIconCount = 0;

		if(dwDirectorySize > 0)
		{
			DWORD dwNewResourceSectionSize = dwDirectorySize + dwIconSize + dwGroupIconSize + dwVersionSize + dwManifestSize;

			dwNewResourceSectionSize = ValidAlignment(dwNewResourceSectionSize, 0x200);

			DWORD dwNewResourceSectionPosition = 0;
			BYTE* lpbNewResourceSection = (BYTE*)malloc(dwNewResourceSectionSize);
			memset(lpbNewResourceSection, 0, dwNewResourceSectionSize);
			memcpy(lpbNewResourceSection, pRootDirectory, dwDirectorySize);
			dwNewResourceSectionPosition += dwDirectorySize;

			pRootDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)lpbNewResourceSection);

			nDirectoryCount = pRootDirectory->NumberOfIdEntries + pRootDirectory->NumberOfNamedEntries;

			pEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pRootDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

			// Third pass
			for(i = 0; i < nDirectoryCount; i++)
			{
				if(pEntry->DataIsDirectory)
				{
					pSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pEntry->OffsetToDirectory + (DWORD)pRootDirectory);

					int nSubDirectoryCount = pSubDirectory->NumberOfIdEntries + pSubDirectory->NumberOfNamedEntries;

					pSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

					for(j = 0; j < nSubDirectoryCount; j++)
					{
						if(pSubEntry->DataIsDirectory)
						{
							pSubSubDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pSubEntry->OffsetToDirectory + (DWORD)pRootDirectory);

							int nSubSubDirectoryCount = pSubSubDirectory->NumberOfIdEntries + pSubSubDirectory->NumberOfNamedEntries;

							pSubSubEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pSubSubDirectory + sizeof(IMAGE_RESOURCE_DIRECTORY));

							for(k = 0; k < nSubSubDirectoryCount; k++)
							{
								if(pSubSubEntry->DataIsDirectory)
								{
									// recurse again!
									//printf("Shouldn't normally get here, resource directory is already 3 levels deep!\n");
								}
								else
								{
									if(!(pSubSubEntry->OffsetToData & 0x8000000))
									{
										pDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pRootDirectory + pSubSubEntry->OffsetToData);
										DWORD dwFileOffset = 0;

										switch(pEntry->Name)
										{
										case RT_ICON:
											if(dwIconCount < lpGroupIconDir->idCount)
											{
												dwFileOffset = RVAToOffset(pDataEntry->OffsetToData, lpMapping);
												memcpy((LPVOID)((DWORD)lpbNewResourceSection + dwNewResourceSectionPosition), (LPVOID)((DWORD)lpMapping + dwFileOffset), pDataEntry->Size);
												
												// blank original to enable higher compression
												memset((LPVOID)((DWORD)lpMapping + dwFileOffset), 0, pDataEntry->Size);

												pDataEntry->OffsetToData = OffsetToRVA(pSecHdr->PointerToRawData + dwNewResourceSectionPosition, lpMapping);

												dwNewResourceSectionPosition += pDataEntry->Size;

												dwIconCount++;
											}
											break;
										case RT_GROUP_ICON:
											if(dwGroupIconCount < lpGroupIconDir->idCount)
											{
												dwFileOffset = RVAToOffset(pDataEntry->OffsetToData, lpMapping);
												memcpy((LPVOID)((DWORD)lpbNewResourceSection + dwNewResourceSectionPosition), (LPVOID)((DWORD)lpMapping + dwFileOffset), pDataEntry->Size);
												
												// blank original to enable higher compression
												memset((LPVOID)((DWORD)lpMapping + dwFileOffset), 0, pDataEntry->Size);

												pDataEntry->OffsetToData = OffsetToRVA(pSecHdr->PointerToRawData + dwNewResourceSectionPosition, lpMapping);

												dwNewResourceSectionPosition += pDataEntry->Size;

												dwGroupIconCount++;
											}
											break;
										case RT_VERSION:
										case 24:	// RT_MANIFEST
											dwFileOffset = RVAToOffset(pDataEntry->OffsetToData, lpMapping);
											memcpy((LPVOID)((DWORD)lpbNewResourceSection + dwNewResourceSectionPosition), (LPVOID)((DWORD)lpMapping + dwFileOffset), pDataEntry->Size);
											
											// blank original to enable higher compression
											memset((LPVOID)((DWORD)lpMapping + dwFileOffset), 0, pDataEntry->Size);

											pDataEntry->OffsetToData = OffsetToRVA(pSecHdr->PointerToRawData + dwNewResourceSectionPosition, lpMapping);

											dwNewResourceSectionPosition += pDataEntry->Size;
											break;
										}
									}
								}

								pSubSubEntry++;
							}
						}

						pSubEntry++;
					}
				}

				pEntry++;
			}

			*dwOutputSize = dwNewResourceSectionSize;
			return lpbNewResourceSection;
		}
	}

	*dwOutputSize = 0;
	return 0;
}

int CCompressDlg::CallbackFunc(size_t length, size_t input, size_t output, void* cbparam)
{
	CCompressDlg* pDlg = (CCompressDlg*)cbparam;

	double fPercent = 0.0;
	fPercent = ((double)(input + pDlg->m_ProgressOffset)/(double)(pDlg->m_ProgressFileSize))*100;
	
	if(fPercent > 100)
		fPercent = 100.0;

	pDlg->m_ctrlCompressionProgress.SetPos((int)fPercent);
	pDlg->m_CompressionProgress.Format("%.02f%%", fPercent);

	pDlg->UpdateData(FALSE);

	return 1;
}

void CCompressDlg::OnCompress() 
{
	UpdateData(TRUE);

	m_ctrlCompressionProgress.SetPos(0);
	m_ctrlCompessedSize.SetPos(0);

	Encrypt((char*)m_SourceFile.GetBuffer(0));	
}

BOOL CCompressDlg::OnInitDialog() 
{
	CTexturedDlg::OnInitDialog();

	m_ctrlCompressionProgress.SetStep(1);
	m_ctrlCompressionProgress.SetRange(0, 100);
	m_ctrlCompressionProgress.SetPos(0);

	m_CompressionProgress = "";

	m_ctrlCompessedSize.SetStep(1);
	m_ctrlCompessedSize.SetRange(0, 100);
	m_ctrlCompessedSize.SetPos(0);

	m_FileSize = "";
	
	UpdateData(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?