BOOL CVersionInfo::ToFile(const CString &strModulePath, LPCTSTR lpszResourceId, WORD wLangId, const bool bReplace) { CString strUseModulePath(strModulePath); if (strUseModulePath.IsEmpty()) { strUseModulePath = m_strModulePath; } if (NULL == lpszResourceId) { //Try resource ID that we loaded from; lpszResourceId = m_lpszResourceId; if (NULL == lpszResourceId) { //Use default lpszResourceId = MAKEINTRESOURCE(1); } } if (0xFFFF == wLangId) { //Try using language that we loaded from wLangId = m_wLangId; if (0xFFFF == wLangId) { //Use neutral wLangId = NULL; } } CVersionInfoBuffer viSaveBuf; Write(viSaveBuf); return UpdateModuleResource(strUseModulePath, lpszResourceId, wLangId, viSaveBuf.GetData(), viSaveBuf.GetPosition(), bReplace); }
BOOL CVersionInfo::FromFile(const CString &strModulePath, LPCTSTR lpszResourceId, WORD wLangId) { CVersionInfoBuffer viLoadBuf; m_wLangId = wLangId; m_lpszResourceId = (LPTSTR)lpszResourceId; //LoadVersionInfoResource will update member variables m_wLangId, m_lpszResourceId, which is awkward, need to change this flow if (!LoadVersionInfoResource(strModulePath, viLoadBuf, lpszResourceId, wLangId)) return FALSE; m_strModulePath = strModulePath; DWORD dwSize = viLoadBuf.GetPosition(); VERSION_INFO_HEADER* pVI = (VERSION_INFO_HEADER*) viLoadBuf.GetData(); ASSERT(!wcscmp(pVI->szKey, L"VS_VERSION_INFO")); VS_FIXEDFILEINFO* pFixedInfo = (VS_FIXEDFILEINFO*)DWORDALIGN(&pVI->szKey[wcslen(pVI->szKey)+1]); memcpy(&m_vsFixedFileInfo, pFixedInfo, sizeof(VS_FIXEDFILEINFO)); // Iterate children StringFileInfo or VarFileInfo BaseFileInfo *pChild = (BaseFileInfo*) DWORDALIGN((DWORD)pFixedInfo + pVI->wValueLength); BOOL bHasVar = FALSE; BOOL bHasStrings = FALSE; BOOL bBlockOrderKnown = FALSE; CStringList lstTranslations; while ((DWORD)pChild < ((DWORD)(pVI) + pVI->wLength)) { if (!wcscmp(pChild->szKey, L"StringFileInfo")) { //It is a StringFileInfo //ASSERT(1 == pChild->wType); //如果类型是0表示二进制内容,类型为1时才包含字符串内容 if (1 != pChild->wType) { //pChild = (BaseFileInfo*)DWORDALIGN((DWORD)pChild + pChild->wLength); //continue; } StringFileInfo* pStringFI = (StringFileInfo*)pChild; ASSERT(!pStringFI->wValueLength); //MSDN says: Specifies an array of zero or one StringFileInfo structures. So there should be only one StringFileInfo at most ASSERT(m_stringFileInfo.IsEmpty()); m_stringFileInfo.FromStringFileInfo(pStringFI); bHasStrings = TRUE; } else { VarFileInfo* pVarInfo = (VarFileInfo*)pChild; //ASSERT(1 == pVarInfo->wType); //如果类型是0表示二进制内容,类型为1时才包含字符串内容 if (1 != pChild->wType) { //pChild = (BaseFileInfo*)DWORDALIGN((DWORD)pChild + pChild->wLength); //continue; } ASSERT(!wcscmp(pVarInfo->szKey, L"VarFileInfo")); ASSERT(!pVarInfo->wValueLength); //Iterate Var elements //There really must be only one Var* pVar = (Var*) DWORDALIGN(&pVarInfo->szKey[wcslen(pVarInfo->szKey)+1]); while ((DWORD)pVar < ((DWORD) pVarInfo + pVarInfo->wLength)) { ASSERT(!bHasVar && "Multiple Vars in VarFileInfo"); ASSERT(!wcscmp(pVar->szKey, L"Translation")); ASSERT(pVar->wValueLength); DWORD *pValue = (DWORD*) DWORDALIGN(&pVar->szKey[wcslen(pVar->szKey)+1]); DWORD *pdwTranslation = pValue; while ((LPBYTE)pdwTranslation < (LPBYTE)pValue + pVar->wValueLength) { CString strStringTableKey; strStringTableKey.Format(_T("%04x%04x"), LOWORD(*pdwTranslation), HIWORD(*pdwTranslation)); lstTranslations.AddTail(strStringTableKey); pdwTranslation++; } bHasVar = TRUE; pVar = (Var*) DWORDALIGN((DWORD)pVar + pVar->wLength); } ASSERT(bHasVar && "No Var in VarFileInfo"); } if (!bBlockOrderKnown) { bBlockOrderKnown = TRUE; m_bRegularInfoOrder = bHasStrings; } pChild = (BaseFileInfo*) DWORDALIGN((DWORD)pChild + pChild->wLength); } #ifdef _DEBUG ASSERT((DWORD)lstTranslations.GetCount() == m_stringFileInfo.GetStringTableCount()); CString strKey = m_stringFileInfo.GetFirstStringTable().GetKey(); POSITION posTranslation = lstTranslations.GetHeadPosition(); while (posTranslation) { CString strTranslation = lstTranslations.GetNext(posTranslation); CString strTranslationUpper (strTranslation); strTranslation.MakeUpper(); ASSERT(m_stringFileInfo.HasStringTable(strTranslation) || m_stringFileInfo.HasStringTable(strTranslationUpper)); } //Verify Write CVersionInfoBuffer viSaveBuf; Write(viSaveBuf); ASSERT(viSaveBuf.GetPosition() == viLoadBuf.GetPosition()); ASSERT(!memcmp(viSaveBuf.GetData(), viLoadBuf.GetData(), viSaveBuf.GetPosition())); CFile fOriginal(_T("f1.res"), CFile::modeCreate | CFile::modeWrite); fOriginal.Write(viLoadBuf.GetData(), viLoadBuf.GetPosition()); fOriginal.Close(); CFile fSaved(_T("f2.res"), CFile::modeCreate | CFile::modeWrite); fSaved.Write(viSaveBuf.GetData(), viSaveBuf.GetPosition()); fSaved.Close(); #endif return TRUE; }