// Sets the offsets in directory entries void CResourceEditor::SetOffsets(CResourceDirectory* resDir, DWORD newResDirAt) { for (int i = 0; i < resDir->CountEntries(); i++) { if (resDir->GetEntry(i)->IsDataDirectory()) { PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->DataIsDirectory = 1; PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->OffsetToDirectory = resDir->GetEntry(i)->GetSubDirectory()->m_dwWrittenAt - newResDirAt; SetOffsets(resDir->GetEntry(i)->GetSubDirectory(), newResDirAt); } else { PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->OffsetToData = resDir->GetEntry(i)->GetDataEntry()->m_dwWrittenAt - newResDirAt; } } }
static void PatchResourcesDirectory(PIMAGE_RESOURCE_DIRECTORY pIRD, PBYTE pBase) { UINT i; pIRD->TimeDateStamp = 0; PIMAGE_RESOURCE_DIRECTORY_ENTRY pIRDE = PIMAGE_RESOURCE_DIRECTORY_ENTRY(pIRD+1); for ( i=0; i < pIRD->NumberOfNamedEntries; i++, pIRDE++ ) PatchResourceEntry(pIRDE, pBase); for ( i=0; i < pIRD->NumberOfIdEntries; i++, pIRDE++ ) PatchResourceEntry(pIRDE, pBase); }
// This function writes into a given place in memory (pbRsrcSec) the edited resource section void CResourceEditor::WriteRsrcSec(BYTE* pbRsrcSec) { BYTE* seeker = pbRsrcSec; queue<CResourceDirectory*> qDirs; // Used to scan the tree by level queue<CResourceDataEntry*> qDataEntries; // Used for writing the data entries queue<CResourceDataEntry*> qDataEntries2; // Used for writing raw resources data queue<CResourceDirectoryEntry*> qStrings; // Used for writing resources' names qDirs.push(m_cResDir); while (!qDirs.empty()) { CResourceDirectory* crd = qDirs.front(); CopyMemory(seeker, &crd->GetInfo(), sizeof(IMAGE_RESOURCE_DIRECTORY)); crd->m_dwWrittenAt = DWORD(seeker); seeker += sizeof(IMAGE_RESOURCE_DIRECTORY); for (int i = 0; i < crd->CountEntries(); i++) { if (crd->GetEntry(i)->HasName()) qStrings.push(crd->GetEntry(i)); if (crd->GetEntry(i)->IsDataDirectory()) qDirs.push(crd->GetEntry(i)->GetSubDirectory()); else { qDataEntries.push(crd->GetEntry(i)->GetDataEntry()); qDataEntries2.push(crd->GetEntry(i)->GetDataEntry()); } IMAGE_RESOURCE_DIRECTORY_ENTRY rDirE = {0,}; rDirE.DataIsDirectory = crd->GetEntry(i)->IsDataDirectory(); rDirE.Id = (crd->GetEntry(i)->HasName()) ? 0 : crd->GetEntry(i)->GetId(); rDirE.NameIsString = (crd->GetEntry(i)->HasName()) ? 1 : 0; CopyMemory(seeker, &rDirE, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); crd->GetEntry(i)->m_dwWrittenAt = DWORD(seeker); seeker += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); } qDirs.pop(); } /* * Write IMAGE_RESOURCE_DATA_ENTRYs. */ while (!qDataEntries.empty()) { CResourceDataEntry* cRDataE = qDataEntries.front(); IMAGE_RESOURCE_DATA_ENTRY rDataE = {0,}; rDataE.CodePage = cRDataE->GetCodePage(); rDataE.Size = cRDataE->GetSize(); CopyMemory(seeker, &rDataE, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); cRDataE->m_dwWrittenAt = DWORD(seeker); seeker += sizeof(IMAGE_RESOURCE_DATA_ENTRY); qDataEntries.pop(); } /* * Write strings */ while (!qStrings.empty()) { CResourceDirectoryEntry* cRDirE = qStrings.front(); PIMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->NameOffset = DWORD(seeker) - DWORD(pbRsrcSec); char* szName = cRDirE->GetName(); WORD iLen = lstrlen(szName); WCHAR* szwName = new WCHAR[iLen+1]; // MultiByteToWideChar return value includes the null char, so -1 iLen = MultiByteToWideChar(CP_ACP, 0, szName, iLen, szwName, iLen) - 1; *(WORD*)seeker = iLen; seeker += sizeof(WORD); CopyMemory(seeker, szwName, iLen*sizeof(WCHAR)); seeker += iLen*sizeof(WCHAR); // Even though the number of chars is predefined a null termination is required *(WORD*)seeker = 0; seeker += sizeof(WORD); delete [] szName; delete [] szwName; qStrings.pop(); } /* * Write raw resource data and set offsets in IMAGE_RESOURCE_DATA_ENTRYs. */ while (!qDataEntries2.empty()) { CResourceDataEntry* cRDataE = qDataEntries2.front(); CopyMemory(seeker, cRDataE->GetData(), cRDataE->GetSize()); PIMAGE_RESOURCE_DATA_ENTRY(cRDataE->m_dwWrittenAt)->OffsetToData = seeker - pbRsrcSec + m_dwResourceSectionVA; seeker += RALIGN(cRDataE->GetSize(), 8); qDataEntries2.pop(); } /* * Set all of the directory entries offsets. */ SetOffsets(m_cResDir, DWORD(pbRsrcSec)); }