// XMLResource.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "Common/XTPPropExchange.h" #include "Common/XTPResourceManager.h" #include "Common/XTPVC80Helpers.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // The one and only application object CWinApp theApp; using namespace std; struct RESOURCE_LANGUAGE { CString strEncoding; CString strLangauge; long wLanguage; }; AFX_INLINE int REPLACEW_S(LPWSTR strReplace, LPCWSTR lpszOld, LPCWSTR lpszNew) { int nOldLength = (strReplace == NULL) ? 0 : (int)wcslen(strReplace); int nSourceLen = (lpszOld == NULL) ? 0 : (int)wcslen(lpszOld); if (nSourceLen == 0 || nOldLength == 0) return 0; int nReplacementLen = (lpszNew == NULL) ? 0 : (int)wcslen(lpszNew); // loop once to figure out the size of the result string int nCount = 0; LPWSTR lpszStart = strReplace; LPWSTR lpszTarget; while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL) { nCount++; lpszStart = lpszTarget + nSourceLen; } // if any changes were made, make them if (nCount > 0) { int nNewLength = nOldLength + (nReplacementLen-nSourceLen)*nCount; //ASSERT(nNewLength <= nOldLength); // not implemented lpszStart = strReplace; // loop again to actually do the work while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL) { int nBalance = nOldLength - int(lpszTarget - strReplace + nSourceLen); MEMMOVE_S(lpszTarget + nReplacementLen, lpszTarget + nSourceLen, nBalance * sizeof(WORD)); MEMCPY_S(lpszTarget, lpszNew, nReplacementLen*sizeof(WORD)); lpszStart = lpszTarget + nReplacementLen; lpszStart[nBalance] = '\0'; nOldLength += (nReplacementLen - nSourceLen); } ASSERT(strReplace[nNewLength] == '\0'); } return nCount; } void PreformatString(LPWSTR strValue) { REPLACEW_S(strValue, L"\\", L"\\\\"); REPLACEW_S(strValue, L"\n", L"\\n"); REPLACEW_S(strValue, L"\r", L"\\r"); REPLACEW_S(strValue, L"\t", L"\\t"); } BOOL FindLanguage(RESOURCE_LANGUAGE* p, WORD wLanguage) { struct { WORD wLanguage; LPCTSTR lpszEncoding; LPCTSTR lpszCaption; } encoding[] = { {MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT), _T("windows-1251"), _T("Russian")}, {MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), _T("shift-jis"), _T("Japanese")}, {MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), _T("windows-1256"), _T("Arabic (Saudi Arabia)")}, {MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT), _T("windows-1250"), _T("Czech")}, {MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT), _T("windows-1252"), _T("Danish")}, {MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), _T("windows-1252"), _T("German (Germany)")}, {MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT), _T("windows-1253"), _T("Greek")}, {MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), _T("windows-1252"), _T("English (United States)")}, {MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), _T("windows-1252"), _T("Spanish (Spain - Modern Sort)")}, {MAKELANGID(LANG_ESTONIAN, SUBLANG_DEFAULT), _T("windows-1257"), _T("Estonian")}, {MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT), _T("windows-1252"), _T("Finnish")}, {MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), _T("windows-1252"), _T("French (France)")}, {MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), _T("windows-1255"), _T("Hebrew")}, {MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT), _T("windows-1250"), _T("Croatian")}, {MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT), _T("windows-1250"), _T("Hungarian")}, {MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), _T("windows-1252"), _T("Italian (Italy)")}, {MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), _T("ks_c_5601"), _T("Korean")}, {MAKELANGID(LANG_LITHUANIAN, SUBLANG_LITHUANIAN), _T("windows-1257"), _T("Lithuanian")}, {MAKELANGID(LANG_LATVIAN, SUBLANG_DEFAULT), _T("windows-1257"), _T("Latvian")}, {MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), _T("windows-1252"), _T("Dutch")}, {MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL), _T("windows-1252"), _T("Norwegian (Bokmal)")}, {MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), _T("windows-1250"), _T("Polish")}, {MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE), _T("windows-1252"), _T("Portuguese (Portugal)")}, {MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), _T("windows-1252"), _T("Portuguese (Brazil)")}, {MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT), _T("windows-1250"), _T("Romanian")}, {MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT), _T("windows-1250"), _T("Slovak")}, {MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT), _T("windows-1250"), _T("Slovenian")}, {MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT), _T("windows-1252"), _T("Swedish")}, {MAKELANGID(LANG_THAI, SUBLANG_DEFAULT), _T("windows-874"), _T("Thai")}, {MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT), _T("windows-1254"), _T("Turkish")}, {MAKELANGID(LANG_UKRAINIAN, SUBLANG_DEFAULT), _T("windows-1251"), _T("Ukrainian ")}, {MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT), _T("windows-1251"), _T("Bulgarian")}, {MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), _T("gb2312"), _T("Chinese (PRC)")}, {MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), _T("big5"), _T("Chinese (Taiwan)")} }; for (int i = 0; i < _countof(encoding); i++) { if (encoding[i].wLanguage == wLanguage) { p->strEncoding = encoding[i].lpszEncoding; p->strLangauge = encoding[i].lpszCaption; p->wLanguage = wLanguage; return TRUE; } } return FALSE; } ULONG_PTR AlignDWord(ULONG_PTR uLong) { return ((uLong + 3) & ~3); } void PX_StringW(CXTPPropExchange* pPX, LPCTSTR pszPropName, LPWSTR str, LPWSTR lpDefault = 0) { if (!str || str[0] == 0) return; WORD dwLength = wcslen(str); LPWSTR lpwString = new WCHAR[(dwLength + 1) * 2 * 2]; memcpy(lpwString, str, (dwLength + 1) * 2); PreformatString(lpwString); BSTR bstrValue = (BSTR)lpwString; PX_Bstr(pPX, pszPropName, bstrValue, (BSTR)lpDefault); BSTR bstrString = (BSTR)lpwString; delete[] lpwString; } void PutDialogTemplate(CXTPPropExchange* pPX, DLGTEMPLATE* pTemplate) { DLGTEMPLATEEX* pTemplateEx = (DLGTEMPLATEEX*)pTemplate; BOOL bTemplateEx = pTemplateEx->signature == 0xFFFF; int style, styleex, x, y, cx, cy, id; LPWORD pItems; if (bTemplateEx) { style = pTemplateEx->style; styleex = pTemplateEx->exStyle; x = pTemplateEx->x; y = pTemplateEx->y; cx = pTemplateEx->cx; cy = pTemplateEx->cy; pItems = (LPWORD)((LPBYTE)pTemplate + sizeof(DLGTEMPLATEEX)); } else { style = pTemplate->style; styleex = pTemplate->dwExtendedStyle; x = pTemplate->x; y = pTemplate->y; cx = pTemplate->cx; cy = pTemplate->cy; pItems = (LPWORD)((LPBYTE)pTemplate + sizeof(DLGTEMPLATE)); } ASSERT(*pItems == 0); ASSERT(*(pItems + 1) == 0); pItems += 2; if (pItems) { PX_StringW(pPX, _T("caption"), (LPWSTR)pItems); pItems += wcslen((LPWSTR)pItems); } pItems += 1; if (style & DS_SETFONT) { int nHeight = *pItems; PX_Int(pPX, _T("fontsize"), nHeight, 8); pItems += bTemplateEx? 3: 1; PX_StringW(pPX, _T("fontface"), (LPWSTR)pItems, L"MS Sans Serif"); pItems += wcslen((LPWSTR)pItems) + 1; } CString strPos; strPos.Format(_T("%i, %i, %i, %i"), x, y, cx, cy); PX_Int(pPX, _T("style"), style); PX_Int(pPX, _T("styleex"), styleex, 0); PX_String(pPX, _T("position"), strPos); pItems = LPWORD((LPBYTE)pTemplate + AlignDWord((LPBYTE)pItems - (LPBYTE)pTemplate)); CXTPPropExchangeEnumeratorPtr secControl(pPX->GetEnumerator(_T("control"))); POSITION pos = secControl->GetPosition(32000); int nCount = bTemplateEx? pTemplateEx->cDlgItems: pTemplate->cdit; for (int i = 0; i < nCount; i++) { DLGITEMTEMPLATE* pItemTemplate = (DLGITEMTEMPLATE*)pItems; DLGITEMTEMPLATEEX* pItemTemplateEx = (DLGITEMTEMPLATEEX*)pItems; CXTPPropExchangeSection sec(secControl->GetNext(pos)); if (bTemplateEx) { style = pItemTemplateEx->style; styleex = pItemTemplateEx->exStyle; x = pItemTemplateEx->x; y = pItemTemplateEx->y; cx = pItemTemplateEx->cx; cy = pItemTemplateEx->cy; id = pItemTemplateEx->id; pItems = LPWORD((LPBYTE)pItemTemplate + sizeof(DLGITEMTEMPLATEEX)); } else { style = pItemTemplate->style; styleex = pItemTemplate->dwExtendedStyle; x = pItemTemplate->x; y = pItemTemplate->y; cx = pItemTemplate->cx; cy = pItemTemplate->cy; id = pItemTemplate->id; pItems = LPWORD((LPBYTE)pItemTemplate + sizeof(DLGITEMTEMPLATE)); } CString strPos; strPos.Format(_T("%i, %i, %i, %i"), x, y, cx, cy); if (id == 65535 || id == -1) id = 0; PX_Int(&sec, _T("id"), id, 0); CString strClass; if (*pItems == 0xFFFF) { switch (*(pItems + 1)) { case 0x0080: strClass = _T("BUTTON"); break; case 0x0081: strClass = _T("EDIT"); break; case 0x0082: strClass = _T("STATIC"); break; case 0x0083: strClass = _T("LISTBOX"); break; case 0x0084: strClass = _T("SCROLLBAR"); break; case 0x0085: strClass = _T("COMBOBOX"); break; } pItems += 2; } else { strClass = (LPWSTR)pItems; pItems += strClass.GetLength() + 1; } PX_String(&sec, _T("class"), strClass, _T("STATIC")); if (*pItems == 0xFFFF) { int nResource = *(pItems + 1); PX_Int(&sec, _T("resource"), nResource); pItems += 2; } else { PX_StringW(&sec, _T("caption"), (LPWSTR)pItems); pItems += wcslen((LPWSTR)pItems) + 1; } PX_Int(&sec, _T("style"), style, WS_CHILD | WS_VISIBLE | WS_GROUP); PX_Int(&sec, _T("styleex"), styleex, 0); PX_String(&sec, _T("position"), strPos); ASSERT(*pItems == 0); pItems += 1; pItems = LPWORD((LPBYTE)pItemTemplate + AlignDWord((LPBYTE)pItems - (LPBYTE)pItemTemplate)); } } void PutMenuItems(CXTPPropExchange* pPX, MENUITEMTEMPLATE*& pItem) { CXTPPropExchangeEnumeratorPtr secMenuItem(pPX->GetEnumerator(_T("menuitem"))); POSITION posMenuItem = secMenuItem->GetPosition(32000); while (TRUE) { CXTPPropExchangeSection sec(secMenuItem->GetNext(posMenuItem)); BOOL bPopup = (pItem->mtOption & MF_POPUP) != 0; BOOL bEnd = (pItem->mtOption & MF_END) != 0; int nID = !bPopup? (int)pItem->mtID: 0; PX_Int(&sec, _T("id"), nID, 0); int nCaptionSize = (int)wcslen(bPopup? pItem->mtString - 1: pItem->mtString); WCHAR* pCaption = !bPopup? pItem->mtString: (WCHAR*)&pItem->mtID; if (pCaption) { PX_StringW(&sec, _T("caption"), pCaption); } pItem = (MENUITEMTEMPLATE*)((LPBYTE)pItem + (pItem->mtOption & MF_POPUP? sizeof(WORD) * 2: sizeof(WORD) * 3) + (nCaptionSize) * 2); if (bPopup) { PutMenuItems(&sec, pItem); } if (bEnd) break; } } struct PROPEXCHANGEENUM { CXTPPropExchangeEnumerator* pEnumerator; POSITION pos; }; BOOL CALLBACK EnumResStringProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) { PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam; ASSERT(pxEnum); if (!pxEnum) return FALSE; HRSRC hRsrc = FindResource(hModule, lpszName, lpszType); if (!hRsrc) return FALSE; HGLOBAL hRsrcData = LoadResource(hModule, hRsrc); LPWSTR lpszData = (LPWSTR)LockResource(hRsrcData); for (int i = 0; i < 16; i++) { if (*lpszData) { CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos)); WORD dwLength = *lpszData; LPWSTR lpwString = new WCHAR[(dwLength + 1) * 2 * 2]; memcpy(lpwString, lpszData + 1, dwLength * 2); lpwString[dwLength] = 0; PreformatString(lpwString); BSTR bstrString = (BSTR)lpwString; int nResource = (((UINT)(UINT_PTR)lpszName - 1) * 16 + i); PX_Int(&sec, _T("id"), nResource); PX_Bstr(&sec, _T("value"), bstrString, 0); delete[] lpwString; lpszData = lpszData + dwLength + 1; } else { lpszData += 1; } } return TRUE; } void ConvertStrings(HMODULE hModule, CXTPPropExchange* pPX) { PROPEXCHANGEENUM pxenum; pxenum.pEnumerator = pPX->GetEnumerator(_T("string")); pxenum.pos = pxenum.pEnumerator->GetPosition(32000); ::EnumResourceNames(hModule, RT_STRING, &EnumResStringProc, (LONG_PTR)&pxenum); delete pxenum.pEnumerator; } BOOL CALLBACK EnumResMenuProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) { PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam; ASSERT(pxEnum); if (!pxEnum) return FALSE; HRSRC hRsrc = FindResource(hModule, lpszName, lpszType); if (!hRsrc) return FALSE; HGLOBAL hRsrcData = LoadResource(hModule, hRsrc); LPBYTE lpszData = (LPBYTE)LockResource(hRsrcData); CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos)); int nResource = (UINT)(UINT_PTR)lpszName; PX_Int(&sec, _T("id"), nResource); lpszData += 4; MENUITEMTEMPLATE* pItem = (MENUITEMTEMPLATE*)lpszData; PutMenuItems(&sec, pItem); return TRUE; } void ConvertMenus(HMODULE hModule, CXTPPropExchange* pPX) { PROPEXCHANGEENUM pxenum; pxenum.pEnumerator = pPX->GetEnumerator(_T("menu")); pxenum.pos = pxenum.pEnumerator->GetPosition(32000); ::EnumResourceNames(hModule, RT_MENU, &EnumResMenuProc, (LONG_PTR)&pxenum); delete pxenum.pEnumerator; } BOOL CALLBACK EnumResDialogProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) { PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam; ASSERT(pxEnum); if (!pxEnum) return FALSE; HRSRC hRsrc = FindResource(hModule, lpszName, lpszType); if (!hRsrc) return FALSE; HGLOBAL hRsrcData = LoadResource(hModule, hRsrc); LPBYTE lpszData = (LPBYTE)LockResource(hRsrcData); CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos)); int nResource = (UINT)(UINT_PTR)lpszName; PX_Int(&sec, _T("id"), nResource); DLGTEMPLATE* pItem = (DLGTEMPLATE*)lpszData; PutDialogTemplate(&sec, pItem); return TRUE; } void ConvertDialogs(HMODULE hModule, CXTPPropExchange* pPX) { PROPEXCHANGEENUM pxenum; pxenum.pEnumerator = pPX->GetEnumerator(_T("dialog")); pxenum.pos = pxenum.pEnumerator->GetPosition(32000); ::EnumResourceNames(hModule, RT_DIALOG, &EnumResDialogProc, (LONG_PTR)&pxenum); delete pxenum.pEnumerator; } int ConvertFile(CString lpszFileName) { HMODULE hModule = LoadLibrary(lpszFileName); ASSERT(hModule); CXTPPropExchangeXMLNode secResources(FALSE, 0, _T("resource")); if (!secResources.OnBeforeExchange()) return 1; BOOL bEncoding = FALSE; RESOURCE_LANGUAGE lan; WORD wLanguage = CXTPResourceManager::GetResourceLanguage(hModule); if (wLanguage == 0) return 1; if (!FindLanguage(&lan, wLanguage)) return FALSE; if (!lan.strEncoding.IsEmpty()) { secResources.SetEncoding(lan.strEncoding); PX_String(&secResources, _T("Language"), lan.strLangauge); PX_Long(&secResources, _T("LANGID"), lan.wLanguage); } ConvertStrings(hModule, &secResources); ConvertMenus(hModule, &secResources); ConvertDialogs(hModule, &secResources); FreeLibrary(hModule); CString strOutput = lpszFileName.Left(lpszFileName.GetLength() - 3) + _T("xml"); secResources.SaveToFile(strOutput, TRUE); return 0; } int _tmain(int argc, TCHAR* argv[], TCHAR* /*envp*/ []) { USES_CONVERSION; int nRetCode = 0; // initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { cerr << "Fatal Error: MFC initialization failed" << endl; return 1; } OleInitialize(0); if (argc != 2) { cerr << "This tool generates xml resources from dll" << endl; cerr << "Usage: XMLResource translationdir" << endl; return 1; } CString strPath = argv[1]; CFileFind finder; BOOL bWorking = finder.FindFile(strPath + _T("\\*.dll")); while (bWorking) { bWorking = finder.FindNextFile(); CString strPath = finder.GetFilePath(); LPSTR lpszFilePath = T2A((LPTSTR)(LPCTSTR)strPath); cout << "Converting " << lpszFilePath << "..." << endl; ConvertFile(finder.GetFilePath()); } OleUninitialize(); return nRetCode; }