fixed bug #1083492 - resource editor unicode conversion is lossy
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4878 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
92229d0a82
commit
c037ecfeed
6 changed files with 143 additions and 87 deletions
|
@ -151,7 +151,7 @@ CResourceEditor::~CResourceEditor() {
|
|||
|
||||
// Adds/Replaces/Removes a resource.
|
||||
// If lpData is 0 UpdateResource removes the resource.
|
||||
bool CResourceEditor::UpdateResource(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
bool CResourceEditor::UpdateResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
CResourceDirectory* nameDir = 0;
|
||||
CResourceDirectory* langDir = 0;
|
||||
CResourceDataEntry* data = 0;
|
||||
|
@ -191,7 +191,7 @@ bool CResourceEditor::UpdateResource(char* szType, char* szName, LANGID wLanguag
|
|||
if (!data) {
|
||||
// Language doesn't yet exist, hence data nither
|
||||
data = new CResourceDataEntry(lpData, dwSize);
|
||||
langDir->AddEntry(new CResourceDirectoryEntry(MAKEINTRESOURCE(wLanguage), data));
|
||||
langDir->AddEntry(new CResourceDirectoryEntry(MAKEINTRESOURCEW(wLanguage), data));
|
||||
}
|
||||
}
|
||||
else if (data) {
|
||||
|
@ -212,21 +212,66 @@ bool CResourceEditor::UpdateResource(char* szType, char* szName, LANGID wLanguag
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResource(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResource(MAKEINTRESOURCE(szType), szName, wLanguage, lpData, dwSize);
|
||||
static WCHAR* CreateUnicodeString(const char* szString) {
|
||||
int iLen = MultiByteToWideChar(CP_ACP, 0, szString, -1, 0, 0);
|
||||
if (iLen == 0)
|
||||
throw runtime_error("Unicode conversion failed");
|
||||
|
||||
WCHAR* szwString = new WCHAR[iLen + 1];
|
||||
|
||||
if (MultiByteToWideChar(CP_ACP, 0, szString, -1, szwString, iLen + 1) == 0)
|
||||
throw runtime_error("Unicode conversion failed");
|
||||
|
||||
return szwString;
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResource(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResource(szType, MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize);
|
||||
static WCHAR* ResStringToUnicode(const char *szString) {
|
||||
if (IS_INTRESOURCE(szString))
|
||||
return MAKEINTRESOURCEW(szString);
|
||||
else
|
||||
return CreateUnicodeString(szString);
|
||||
}
|
||||
|
||||
static void FreeUnicodeResString(WCHAR* szwString) {
|
||||
if (!IS_INTRESOURCE(szwString))
|
||||
delete [] szwString;
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResourceW(WORD szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResourceW(MAKEINTRESOURCEW(szType), szName, wLanguage, lpData, dwSize);
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResourceW(WCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResourceW(szType, MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize);
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResourceA(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
WCHAR* szwType = ResStringToUnicode(szType);
|
||||
WCHAR* szwName = ResStringToUnicode(szName);
|
||||
|
||||
bool result = UpdateResourceW(szwType, szwName, wLanguage, lpData, dwSize);
|
||||
|
||||
FreeUnicodeResString(szwType);
|
||||
FreeUnicodeResString(szwName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResourceA(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResourceA(MAKEINTRESOURCE(szType), szName, wLanguage, lpData, dwSize);
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResourceA(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResourceA(szType, MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize);
|
||||
}
|
||||
|
||||
bool CResourceEditor::UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
return UpdateResource(MAKEINTRESOURCE(szType), MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize);
|
||||
return UpdateResourceW(MAKEINTRESOURCEW(szType), MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize);
|
||||
}
|
||||
|
||||
// Returns a copy of the requested resource
|
||||
// Returns 0 if the requested resource can't be found
|
||||
BYTE* CResourceEditor::GetResource(char* szType, char* szName, LANGID wLanguage) {
|
||||
BYTE* CResourceEditor::GetResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage) {
|
||||
CResourceDirectory* nameDir = 0;
|
||||
CResourceDirectory* langDir = 0;
|
||||
CResourceDataEntry* data = 0;
|
||||
|
@ -255,9 +300,21 @@ BYTE* CResourceEditor::GetResource(char* szType, char* szName, LANGID wLanguage)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BYTE* CResourceEditor::GetResourceA(char* szType, char* szName, LANGID wLanguage) {
|
||||
WCHAR* szwType = ResStringToUnicode(szType);
|
||||
WCHAR* szwName = ResStringToUnicode(szName);
|
||||
|
||||
BYTE* result = GetResourceW(szwType, szwName, wLanguage);
|
||||
|
||||
FreeUnicodeResString(szwType);
|
||||
FreeUnicodeResString(szwName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the size of the requested resource
|
||||
// Returns -1 if the requested resource can't be found
|
||||
int CResourceEditor::GetResourceSize(char* szType, char* szName, LANGID wLanguage) {
|
||||
int CResourceEditor::GetResourceSize(WCHAR* szType, WCHAR* szName, LANGID wLanguage) {
|
||||
CResourceDirectory* nameDir = 0;
|
||||
CResourceDirectory* langDir = 0;
|
||||
CResourceDataEntry* data = 0;
|
||||
|
@ -462,7 +519,7 @@ bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName,
|
|||
CResourceDirectory* CResourceEditor::ScanDirectory(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan) {
|
||||
// Create CResourceDirectory from rdToScan
|
||||
CResourceDirectory* rdc = new CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY(rdToScan));
|
||||
char* szName;
|
||||
WCHAR* szName;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY rde = NULL;
|
||||
|
||||
// Go through all entries of this resource directory
|
||||
|
@ -482,16 +539,14 @@ CResourceDirectory* CResourceEditor::ScanDirectory(PRESOURCE_DIRECTORY rdRoot, P
|
|||
if (rd.NameString.NameIsString) {
|
||||
PIMAGE_RESOURCE_DIR_STRING_U rds = PIMAGE_RESOURCE_DIR_STRING_U(rd.NameString.NameOffset + (char*)rdRoot);
|
||||
|
||||
int mbsSize = WideCharToMultiByte(CP_ACP, 0, rds->NameString, ConvertEndianness(rds->Length), 0, 0, 0, 0);
|
||||
szName = new char[mbsSize+1];
|
||||
if (!WideCharToMultiByte(CP_ACP, 0, rds->NameString, ConvertEndianness(rds->Length), szName, mbsSize, 0, 0)) {
|
||||
throw runtime_error("Unicode conversion failed");
|
||||
}
|
||||
szName[mbsSize] = 0;
|
||||
size_t nameSize = ConvertEndianness(rds->Length);
|
||||
szName = new WCHAR[nameSize+1];
|
||||
wcsncpy(szName, rds->NameString, nameSize);
|
||||
szName[nameSize] = 0;
|
||||
}
|
||||
// Else, set the name to this entry's id
|
||||
else
|
||||
szName = MAKEINTRESOURCE(ConvertEndianness(rdToScan->Entries[i].Id));
|
||||
szName = MAKEINTRESOURCEW(ConvertEndianness(rdToScan->Entries[i].Id));
|
||||
|
||||
if (rd.DirectoryOffset.DataIsDirectory)
|
||||
rdc->AddEntry(
|
||||
|
@ -594,18 +649,12 @@ void CResourceEditor::WriteRsrcSec(BYTE* pbRsrcSec) {
|
|||
|
||||
PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->NameString.NameOffset = ConvertEndianness(DWORD(seeker) - DWORD(pbRsrcSec));
|
||||
|
||||
char* szName = cRDirE->GetName();
|
||||
WORD iLen = strlen(szName) + 1;
|
||||
WCHAR *szwName = new WCHAR[iLen];
|
||||
|
||||
// MultiByteToWideChar return value includes the null char, so -1
|
||||
iLen = MultiByteToWideChar(CP_ACP, 0, szName, iLen, szwName, iLen) - 1;
|
||||
if (iLen == (WORD) -1)
|
||||
throw runtime_error("Unicode conversion failed");
|
||||
WCHAR* szName = cRDirE->GetName();
|
||||
WORD iLen = wcslen(szName) + 1;
|
||||
|
||||
*(WORD*)seeker = ConvertEndianness(iLen);
|
||||
seeker += sizeof(WORD);
|
||||
CopyMemory(seeker, szwName, iLen*sizeof(WCHAR));
|
||||
CopyMemory(seeker, szName, iLen*sizeof(WCHAR));
|
||||
seeker += iLen*sizeof(WCHAR);
|
||||
|
||||
// Even though the number of chars is predefined a null termination is required
|
||||
|
@ -613,7 +662,6 @@ void CResourceEditor::WriteRsrcSec(BYTE* pbRsrcSec) {
|
|||
seeker += sizeof(WORD);
|
||||
|
||||
delete [] szName;
|
||||
delete [] szwName;
|
||||
|
||||
qStrings.pop();
|
||||
}
|
||||
|
@ -711,10 +759,10 @@ CResourceDirectoryEntry* CResourceDirectory::GetEntry(unsigned int i) {
|
|||
void CResourceDirectory::AddEntry(CResourceDirectoryEntry* entry) {
|
||||
int i = 0;
|
||||
if (entry->HasName()) {
|
||||
char* szEntName = entry->GetName();
|
||||
WCHAR* szEntName = entry->GetName();
|
||||
for (i = 0; i < m_rdDir.NumberOfNamedEntries; i++) {
|
||||
char* szName = m_vEntries[i]->GetName();
|
||||
int cmp = strcmp(szName, szEntName);
|
||||
WCHAR* szName = m_vEntries[i]->GetName();
|
||||
int cmp = wcscmp(szName, szEntName);
|
||||
delete [] szName;
|
||||
if (cmp == 0) {
|
||||
delete [] szEntName;
|
||||
|
@ -754,19 +802,19 @@ int CResourceDirectory::CountEntries() {
|
|||
// Returns the index of a directory entry with the specified name
|
||||
// Name can be a string or an id
|
||||
// Returns -1 if can not be found
|
||||
int CResourceDirectory::Find(char* szName) {
|
||||
int CResourceDirectory::Find(WCHAR* szName) {
|
||||
if (IS_INTRESOURCE(szName))
|
||||
return Find((WORD) (DWORD) szName);
|
||||
else
|
||||
if (szName[0] == '#')
|
||||
return Find(WORD(atoi(szName + 1)));
|
||||
return Find(WORD(wcstol(szName + 1, NULL, 10)));
|
||||
|
||||
for (unsigned int i = 0; i < m_vEntries.size(); i++) {
|
||||
if (!m_vEntries[i]->HasName())
|
||||
continue;
|
||||
|
||||
char* szEntName = m_vEntries[i]->GetName();
|
||||
int cmp = strcmp(szName, szEntName);
|
||||
WCHAR* szEntName = m_vEntries[i]->GetName();
|
||||
int cmp = wcscmp(szName, szEntName);
|
||||
delete [] szEntName;
|
||||
|
||||
if (!cmp)
|
||||
|
@ -830,7 +878,7 @@ void CResourceDirectory::Destroy() {
|
|||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDirectory* rdSubDir) {
|
||||
CResourceDirectoryEntry::CResourceDirectoryEntry(WCHAR* szName, CResourceDirectory* rdSubDir) {
|
||||
if (IS_INTRESOURCE(szName)) {
|
||||
m_bHasName = false;
|
||||
m_szName = 0;
|
||||
|
@ -838,14 +886,14 @@ CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDirector
|
|||
}
|
||||
else {
|
||||
m_bHasName = true;
|
||||
m_szName = new char[strlen(szName)+1];
|
||||
strcpy(m_szName, szName);
|
||||
m_szName = new WCHAR[wcslen(szName)+1];
|
||||
wcscpy(m_szName, szName);
|
||||
}
|
||||
m_bIsDataDirectory = true;
|
||||
m_rdSubDir = rdSubDir;
|
||||
}
|
||||
|
||||
CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDataEntry* rdeData) {
|
||||
CResourceDirectoryEntry::CResourceDirectoryEntry(WCHAR* szName, CResourceDataEntry* rdeData) {
|
||||
if (IS_INTRESOURCE(szName)) {
|
||||
m_bHasName = false;
|
||||
m_szName = 0;
|
||||
|
@ -853,8 +901,8 @@ CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDataEntr
|
|||
}
|
||||
else {
|
||||
m_bHasName = true;
|
||||
m_szName = new char[strlen(szName)+1];
|
||||
strcpy(m_szName, szName);
|
||||
m_szName = new WCHAR[wcslen(szName)+1];
|
||||
wcscpy(m_szName, szName);
|
||||
}
|
||||
m_bIsDataDirectory = false;
|
||||
m_rdeData = rdeData;
|
||||
|
@ -874,17 +922,17 @@ bool CResourceDirectoryEntry::HasName() {
|
|||
}
|
||||
|
||||
// Don't forget to free the memory used by the string after usage!
|
||||
char* CResourceDirectoryEntry::GetName() {
|
||||
WCHAR* CResourceDirectoryEntry::GetName() {
|
||||
if (!m_bHasName)
|
||||
return 0;
|
||||
char* szName = 0;
|
||||
szName = new char[strlen(m_szName)+1];
|
||||
strcpy(szName, m_szName);
|
||||
WCHAR* szName = 0;
|
||||
szName = new WCHAR[wcslen(m_szName)+1];
|
||||
wcscpy(szName, m_szName);
|
||||
return szName;
|
||||
}
|
||||
|
||||
int CResourceDirectoryEntry::GetNameLength() {
|
||||
return strlen(m_szName);
|
||||
return wcslen(m_szName);
|
||||
}
|
||||
|
||||
WORD CResourceDirectoryEntry::GetId() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue