////////////////////////////////////////////////////////////////////////// // // This application will generate a localized binary given in input // a source binary and two token files. // // The format of the token file is: // [[TYPE ID|RES ID|Item ID|Flags|Status Flags|Item Name]]= // this is the standar format used by several token file tools in MS. // /////////////////////////////////////////////////////////////////////////////// // // Other DLL used: IODLL.DLL // /////////////////////////////////////////////////////////////////////////////// // // Author: Alessandro Muti // Date: 01-16-95 // /////////////////////////////////////////////////////////////////////////////// #include #include "main.h" #include #include #include ////////////////////////////////////////////////////////////////////////// #define BANNER "Microsoft (R) 32-bit RLTools Version 3.5 (Build %d)\r\n" \ "Copyright (C) Microsoft Corp. 1991-1998. All Rights reserved.\r\n"\ "\r\n" \ "Binary file generator utility.\r\n\r\n" #ifdef _DEBUG #define BUILDSTAMP "Build: " __DATE__ " " __TIME__ " (" __TIMESTAMP__ ")\r\n\r\n" #endif // Need to split the help screen in two since it is too long. // The good thing to do would be to put this string in a message table // To be done... char strHelp0[] = \ "BINGEN [-w|n] [-h|?] [-b|s|f] [-p cp] [-{i|o} Pri Sub] [-d char] \r\n"\ " [-{t|u|r|a|x} files] \r\n"\ " \r\n"\ " -w (Show warning messages) \r\n"\ " -? or -h (Show more complete help using winhelp) \r\n"\ " -b (Extract bitmaps and icons) \r\n"\ " -c (Extract embedded gifs, htmls, infs and other binaries) \r\n"\ " -y (Extract Static Control alignment style) \r\n"\ " -l (Lean mode and do not append redundant resources) \r\n"\ " -s (Split Message table messages at \\n\\r) \r\n"\ " -f (Add/Use font information field for dialogs) \r\n"\ " -n (Nologo) \r\n"\ " -v (Ignore selected version stamp information) \r\n"\ " -p CodePage (Default code page of text in project token file) \r\n"\ " -d Character (Default for unmappable characters) \r\n"\ " \r\n"\ "<> \r\n"\ " -t InputExeFile OutputTokenFile \r\n"\ " (Extract token file) \r\n"\ " -u InputExeFile InputUSTokFile InputLOCTokFile OutputExeFile \r\n"\ " (Replace old lang resources with localized tokens) \r\n"\ " -r InputExeFile InputLOCTokFile OutputExeFile \r\n"\ " (Replace old lang resources with localized tokens) \r\n"\ " (Doesn't perform any consistency check) \r\n"\ " -a InputExeFile InputLOCTokFile OutputExeFile \r\n"\ " (Append resources in localized tokens) \r\n"\ " \r\n"; char strHelp1[] = \ "<> \r\n"\ " -i PriLangId SecLangId (Primary- and Sub-Lang IDs, dec/hex, Input file) \r\n"\ " -o PriLangId SecLangId (Primary- and Sub-Lang IDs, dec/hex, Output file) \r\n"\ " \r\n"\ " -x InputRuleFile (Pseudo translation options) \r\n"\ " -m InputSymbolPath OutputSymbolPath \ (Update symbol checksum if neccesory) \r\n"; ////////////////////////////////////////////////////////////////////////// CMainApp::CMainApp() { m_dwFlags = NO_OPTION; m_dwReturn = ERROR_NO_ERROR; m_StdOutput = GetStdHandle(STD_OUTPUT_HANDLE); m_StdError = GetStdHandle(STD_ERROR_HANDLE); // Check if we have being piped to a file BY_HANDLE_FILE_INFORMATION HndlFileInfo; if(GetFileInformationByHandle(m_StdOutput, &HndlFileInfo) || GetFileInformationByHandle(m_StdError, &HndlFileInfo)) m_dwFlags |= PIPED; m_strBuffer1 = ""; m_strBuffer2 = ""; m_pBuf = new BYTE[MAX_BUF_SIZE]; m_wIDNotFound = 0; m_wCntxChanged = 0; m_wResized = 0; // // Set default values for Language // m_usIPriLangId = -1; m_usISubLangId = -1; m_usOPriLangId = -1; m_usOSubLangId = -1; m_uiCodePage = GetACP(); m_unmappedChar = '?'; m_strSymPath = ""; m_strOutputSymPath = ""; } CMainApp::~CMainApp() { if(m_pBuf) delete m_pBuf; } ////////////////////////////////////////////////////////////////////////// CMainApp::Error_Codes CMainApp::ParseCommandLine(int argc, char ** argv) { char * pArgument; int count = 0; if(argc==1) m_dwFlags |= HELP; while(++count0;i--) str += (char)ch; return str.GetBuffer(0); } int __cdecl CMainApp::WriteCon(int iFlags, const char * lpstr, ...) { DWORD dwWritten; va_list ptr; va_start(ptr, lpstr); _vsnprintf(m_strBuffer1.GetBuffer(MAX_STR_SIZE), MAX_STR_SIZE, lpstr, ptr); m_strBuffer1.ReleaseBuffer(); // Check if we want to have the handle sent to both out and err if((iFlags==CONBOTH) && (IsFlag(PIPED))) { WriteFile(m_StdError, m_strBuffer1, m_strBuffer1.GetLength(), &dwWritten, NULL); WriteFile(m_StdOutput, m_strBuffer1, m_strBuffer1.GetLength(), &dwWritten, NULL); return dwWritten; } if((iFlags==CONWRN)) { if(IsFlag(WARNING)) WriteFile(m_StdError, m_strBuffer1, m_strBuffer1.GetLength(), &dwWritten, NULL); return dwWritten; } if(iFlags==CONERR) WriteFile(m_StdError, m_strBuffer1, m_strBuffer1.GetLength(), &dwWritten, NULL); else WriteFile(m_StdOutput, m_strBuffer1, m_strBuffer1.GetLength(), &dwWritten, NULL); return dwWritten; } int CMainApp::SetReturn(int rc) { return (m_dwReturn = rc); } //////////////////////////////////////////////// // Will convert the string strNum in to a short USHORT CMainApp::GetLangID(CString strNum) { strNum.MakeUpper(); // If is there is any of this char "ABCDEFX" assume is an hex number return LOWORD(strtol(strNum, NULL, ((strNum.FindOneOf("ABCDEFX")!=-1) ? 16:10))); } UINT CMainApp::GetCodePage(CString strNum) { strNum.MakeUpper(); // If is there is any of this char "ABCDEFX" assume is an hex number return strtol(strNum, NULL, ((strNum.FindOneOf("ABCDEFX")!=-1) ? 16:10)); } #ifdef NOSLASH LPCSTR CMainApp::Format(CString strTmp) { int iPos; char * pStr = strTmp.GetBuffer(0); char * pStrStart = pStr; int i = 0; m_strBuffer2 = strTmp; while((pStr = strchr(pStr, '\\'))) { iPos = pStr++ - pStrStart + i++; m_strBuffer2 = m_strBuffer2.Left(iPos) + "\\\\" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-1); } while((iPos = m_strBuffer2.Find('\t'))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\\t" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-1); while((iPos = m_strBuffer2.Find('\n'))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\\n" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-1); while((iPos = m_strBuffer2.Find('\r'))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\\r" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-1); return m_strBuffer2; } LPCSTR CMainApp::UnFormat(CString strTmp) { int iPos; char * pStr = strTmp.GetBuffer(0); char * pStrStart = pStr; int i = 0; m_strBuffer2 = strTmp; while((pStr = strstr(pStr, "\\\\"))) { iPos = pStr - pStrStart - i++; pStr += 2; m_strBuffer2 = m_strBuffer2.Left(iPos) + "\\" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-2); } while((iPos = m_strBuffer2.Find("\\t"))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\t" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-2); while((iPos = m_strBuffer2.Find("\\n"))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\n" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-2); while((iPos = m_strBuffer2.Find("\\r"))!=-1) m_strBuffer2 = m_strBuffer2.Left(iPos) + "\r" + m_strBuffer2.Right(m_strBuffer2.GetLength()-iPos-2); return m_strBuffer2; } #endif LPCSTR CMainApp::Format(CString strTmp) { char * pStr = strTmp.GetBuffer(0); char * pDest = m_strBuffer2.GetBuffer(MAX_STR_SIZE); char * pNext; while(*pStr) { if(!IsDBCSLeadByteEx(m_uiCodePage, *pStr)) { switch(*pStr) { case '\\': *pDest++ = '\\'; *pDest++ = '\\'; break; case '\t': *pDest++ = '\\'; *pDest++ = 't'; break; case '\r': *pDest++ = '\\'; *pDest++ = 'r'; break; case '\n': *pDest++ = '\\'; *pDest++ = 'n'; break; default: *pDest++ = *pStr; break; } } else { memcpy( pDest, pStr, 2 ); pDest += 2; } pStr = CharNextExA((WORD)m_uiCodePage, pStr, 0); } *pDest = '\0'; m_strBuffer2.ReleaseBuffer(-1); return m_strBuffer2; } LPCSTR CMainApp::UnFormat(CString strTmp) { m_strBuffer2 = strTmp; int i = m_strBuffer2.GetLength(); char * pStr = m_strBuffer2.GetBuffer(0); char * pNext; while(*pStr) { if(*pStr=='\\' && !IsDBCSLeadByteEx(m_uiCodePage, *pStr)) { pNext = CharNextExA((WORD)m_uiCodePage, pStr, 0); switch(*pNext) { case '\\': *pStr = '\\'; break; case 't': *pStr = '\t'; break; case 'n': *pStr = '\n'; break; case 'r': *pStr = '\r'; break; default: break; } pStr = pNext; pNext = CharNextExA((WORD)m_uiCodePage, pNext, 0); memmove(pStr, pNext, --i); } else { //DBCS shorten length by 2 if (IsDBCSLeadByteEx(m_uiCodePage, *pStr)) i-=2; else i--; pStr = CharNextExA((WORD)m_uiCodePage, pStr, 0); } } m_strBuffer2.ReleaseBuffer(-1); return m_strBuffer2; } int CMainApp::IoDllError(int iError) { CString str = ""; switch (iError) { case 0: break; case ERROR_HANDLE_INVALID: str = "Invalid handle."; break; case ERROR_READING_INI: str = "Error reading WIN.INI file."; break; case ERROR_NEW_FAILED: str = "Running low on memory."; break; case ERROR_FILE_OPEN: str = "Error opening file."; break; case ERROR_FILE_CREATE: str = "Error creating file."; break; case ERROR_FILE_INVALID_OFFSET: str = "File corruption detected."; break; case ERROR_FILE_READ: str = "Error reading file."; break; case ERROR_DLL_LOAD: str = "Error loading R/W DLL."; break; case ERROR_DLL_PROC_ADDRESS: str = "Error loading R/W procedure."; break; case ERROR_RW_LOADIMAGE: str = "Error loading R/W image."; break; case ERROR_RW_PARSEIMAGE: str = "Error parsing R/W image."; break; case ERROR_RW_NOTREADY: str = "Error: R/W not ready?"; break; case ERROR_RW_BUFFER_TOO_SMALL: str = "Running low on memory?"; break; case ERROR_RW_INVALID_FILE: str = "Invalid R/W file."; break; case ERROR_RW_IMAGE_TOO_BIG: str = "Can't load HUGE image."; break; case ERROR_RW_TOO_MANY_LEVELS: str = "Resource directory too deep."; break; case ERROR_RW_NO_RESOURCES: str = "This file contains no resources."; break; case ERROR_IO_INVALIDITEM: str = "Invalid resource item."; break; case ERROR_IO_INVALIDID: str = "Invalid resource ID."; break; case ERROR_IO_INVALID_DLL: str = "Unrecognized file format."; break; case ERROR_IO_TYPE_NOT_SUPPORTED: str = "Type not supported."; break; case ERROR_IO_INVALIDMODULE: str = "Invalid module."; break; case ERROR_IO_RESINFO_NULL: str = "ResInfo is NULL?"; break; case ERROR_IO_UPDATEIMAGE: str = "Error updating image."; break; case ERROR_IO_FILE_NOT_SUPPORTED: str = "File not supported."; break; case ERROR_IO_CHECKSUM_MISMATCH: str = "Symbol file checksum mismatch."; break; case ERROR_IO_SYMBOLFILE_NOT_FOUND: str = "Symbol file not found."; break; case ERROR_FILE_SYMPATH_NOT_FOUND: str = "Output symbol path not found."; break; case ERROR_RW_VXD_MSGPAGE: str = "The specified VxD file contains a message page as its"; str += " last page. This may cause the VxD not to work. Please"; str += " inform the development team of the problem with this file."; break; case ERROR_OUT_OF_DISKSPACE: str = "Out of disk space."; break; case ERROR_RES_NOT_FOUND: str = "Resource not found."; break; default: if(iError-LAST_ERROR>0) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, iError-LAST_ERROR, MAKELANGID(LANG_NEUTRAL,LANG_NEUTRAL), str.GetBuffer(1024), 1024, NULL); str.ReleaseBuffer(); } break; } if (!str.IsEmpty()) { WriteCon(CONERR, "%s: %s\r\n", (iError < LAST_WRN) ? "IODLL Warning" : "IODLL Error", str); SetReturn(iError); } return iError; } // Helper end ///////////////////////////////////////////////////////////////////////////////////////////////////// CMainApp::Error_Codes CMainApp::GenerateFile() { Error_Codes bRet; // Before we procede let's give the global info to the IODLL SETTINGS settings; settings.cp = m_uiCodePage; settings.bAppend = IsFlag(APPEND); settings.bUpdOtherResLang = TRUE; //we save this option for future settings.szDefChar[0] = m_unmappedChar; settings.szDefChar[1] = '\0'; RSSetGlobals(settings); // Here we decide what is the action we have to take if(IsFlag(EXTRACT)) { // we want to generate a token file bRet = TokGen(); } else if(IsFlag(APPEND) | IsFlag(REPLACE) | IsFlag(UPDATE) ) { // we want to generate a binary bRet = BinGen(); } return bRet; } // Main application CMainApp theApp; ////////////////////////////////////////////////////////////////////////// int _cdecl main(int argc, char** argv) { if(theApp.ParseCommandLine(argc, argv)){ return theApp.ReturnCode(); } theApp.GenerateFile(); return theApp.ReturnCode(); } //////////////////////////////////////////////////////////////////////////