|
|
//////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
//
// Author: Alessandro Muti
// Date: 12/02/94
//
///////////////////////////////////////////////////////////////////////////////
#include <afx.h>
#include "iodll.h"
#include "main.h"
#include "vktbl.h"
extern CMainApp theApp;
#define RECURSIVE 0x10
#define WARNINGS 0x20
///////////////////////////////////////////////////////////////////////////////
CString CreateName(CString & strTokenName, CString strExt, int iID) { CString strOutputName = strTokenName; int iNamePos = strTokenName.ReverseFind('\\'); if(iNamePos!=-1) { strOutputName = strTokenName.Right(strTokenName.GetLength()-iNamePos-1); } else if(iNamePos = strTokenName.ReverseFind(':')!=-1){ strOutputName = strTokenName.Right(strTokenName.GetLength()-iNamePos-1); }
CString strID = ""; // subst with ID name
_itoa(iID++, strID.GetBuffer(10), 10); strID.ReleaseBuffer(-1);
// Check the length of the name
iNamePos = strOutputName.Find('.'); if(iNamePos!=-1) strOutputName.SetAt(iNamePos, '_');
strOutputName = strOutputName + "_" + strID + strExt; return strOutputName; }
CString CreateName(CString & strTokenName, CString strExt, CString strIdName) { CString strOutputName = strTokenName; int iNamePos = strTokenName.ReverseFind('\\'); if(iNamePos!=-1) { strOutputName = strTokenName.Right(strTokenName.GetLength()-iNamePos-1); } else if(iNamePos = strTokenName.ReverseFind(':')!=-1){ strOutputName = strTokenName.Right(strTokenName.GetLength()-iNamePos-1); }
iNamePos = strOutputName.Find('.'); if(iNamePos!=-1) strOutputName.SetAt(iNamePos, '_');
iNamePos = strIdName.Find(':'); if (iNamePos!=-1) strIdName.SetAt(iNamePos, '_');
iNamePos = strIdName.Find('\\'); if (iNamePos!=-1) strIdName.SetAt(iNamePos, '_');
strOutputName = strOutputName + "_" + strIdName + strExt; return strOutputName; }
///////////////////////////////////////////////////////////////////////////////
// This function will parse the source file and create the token file
CMainApp::Error_Codes CMainApp::TokGen() { Error_Codes ReturnErr = ERR_NOERROR;
WriteCon(CONERR, "%s\r\n", CalcTab("", 79, '-'));
// Open the iodll.dll using the first file name
HANDLE hModule = RSOpenModule(m_strInExe, NULL); if ((int)(INT_PTR)hModule < LAST_ERROR) { // error or warning
WriteCon(CONERR, "%s", CalcTab(m_strInExe, m_strInExe.GetLength()+5, ' ')); IoDllError((int)(INT_PTR)hModule); return ERR_FILE_NOTSUPP; } else { // before we do anything else we have to check how many languages we have in the file
CString strLang; char szLang[8]; BOOL b_multi_lang = FALSE; USHORT usInputLang = MAKELANGID(m_usIPriLangId, m_usISubLangId);
if((b_multi_lang = RSLanguages(hModule, strLang.GetBuffer(1024))) && !IsFlag(INPUT_LANG)) { // this is a multiple language file but we don't have an input language specified
// Fail, but warn the user that he has to set the input language to continue.
strLang.ReleaseBuffer(); WriteCon(CONERR, "Multiple language file. Please specify an input language %s.\r\n", strLang); theApp.SetReturn(ERROR_FILE_MULTILANG); goto exit; }
// Convert the language in to the hex value
sprintf(szLang,"0x%3.3X", usInputLang);
// Check if the input language that we got is a valid one
if(IsFlag(INPUT_LANG) && strLang.Find(szLang)==-1) { WriteCon(CONERR, "The language %s in not a valid language for this file.\r\n", szLang); WriteCon(CONERR, "Valid languages are: %s.\r\n", strLang); theApp.SetReturn(ERROR_RES_NOT_FOUND); goto exit; }
// Check if the user is extracting the neutral language
if(!usInputLang) usInputLang = 0xFFFF;
// Open the output file
CStdioFile fileOut; if(!fileOut.Open(m_strTgtTok, CFile::modeCreate | CFile::modeReadWrite)) { WriteCon(CONERR, "Cannot create file: %s\r\n", CalcTab(m_strTgtTok, m_strTgtTok.GetLength()+5, ' ')); return ERR_FILE_CREATE; }
CString strOutputDir = ""; CString strFileName = m_strInExe; int pos = m_strInExe.ReverseFind('\\'); if(pos!=-1) { strFileName = m_strInExe.Right(m_strInExe.GetLength()-pos-1); } else if((pos = m_strInExe.ReverseFind(':'))!=-1) { strFileName = m_strInExe.Right(m_strInExe.GetLength()-pos-1); }
pos = m_strTgtTok.ReverseFind('\\'); if(pos!=-1) { strOutputDir = m_strTgtTok.Left(pos+1); } else if((pos = m_strTgtTok.ReverseFind(':'))!=-1) { strOutputDir = m_strTgtTok.Left(pos+1); }
// inform the user ...
WriteCon(CONOUT, "Processing\t"); WriteCon(CONBOTH, "%s", CalcTab(strFileName, strFileName.GetLength()+5, ' '));
if (IsFlag(WARNING)) WriteCon(CONOUT, "\r\n");
LPCSTR lpszType = 0L; LPCSTR lpszRes = 0L; DWORD dwLang = 0L; DWORD dwItem = 0L; DWORD dwItemID = 0L; LPRESITEM lpResItem = NULL;
CString strToken; CString strResName; CString strCaption; WORD wFlag; BOOL bSkip = FALSE; BOOL bSkipEmpty = FALSE; BOOL bSkipLang = FALSE; WORD wCount = 0;
WORD wMsgCount = 0; int iPos = 1; int iBmpIdCount = 0;
BOOL bVersionStampOnly = TRUE; BOOL bCustomResource = FALSE;
while ((lpszType = RSEnumResType(hModule, lpszType))) {
// Check if is one of the type we care about
if(HIWORD(lpszType)==0) { switch(LOWORD(lpszType)) { case 2: case 3: if(theApp.IsFlag(CMainApp::BITMAPS)) bSkip = FALSE; else bSkip = TRUE; break; case 4: case 5: case 6: case 11: bVersionStampOnly = FALSE; case 9: case 10: case 16: bSkip = FALSE; break; case 23: case 240: case 1024: case 2110: if(theApp.IsFlag(CMainApp::GIFHTMLINF)) bSkip = FALSE; else bSkip = TRUE; bVersionStampOnly = FALSE; bCustomResource = TRUE; break; default: bSkip = TRUE; } } else { if (lstrcmp (lpszType, "REGINST") == 0) { if(theApp.IsFlag(CMainApp::GIFHTMLINF)) bSkip = FALSE; else bSkip = TRUE; bCustomResource = TRUE; } else { bSkip = FALSE; } bVersionStampOnly = FALSE; }
lpszRes = 0L; dwLang = 0L; dwItem = 0L;
while ((!bSkip) && (lpszRes = RSEnumResId(hModule, lpszType, lpszRes))) { while ((dwLang = RSEnumResLang(hModule, lpszType, lpszRes, dwLang))) {
// Check if we have to skip this language
if(b_multi_lang && (LOWORD(dwLang)!=usInputLang)) bSkipLang = TRUE; else bSkipLang = FALSE;
while ((!bSkipLang) && (dwItem = RSEnumResItemId(hModule, lpszType, lpszRes, dwLang, dwItem))) {
// Now Get the Data
DWORD dwImageSize = RSGetResItemData( hModule, lpszType, lpszRes, dwLang, dwItem, m_pBuf, MAX_BUF_SIZE ); lpResItem = (LPRESITEM)m_pBuf;
if((wCount++ % 50)==0 && !(IsFlag(WARNING))) WriteCon(CONOUT, ".");
if (HIWORD(lpszType)) { if (lstrcmp (lpszType,"REGINST") == 0) { //
// Currently there is no id for REGINST defined
// in nt. We just use this 2200 for now.
//
lpResItem->dwTypeID = 2200; } }
// Check if we want or not empty strings
// Allow empty strings for Dialog resources
switch(lpResItem->dwTypeID) { case 4: case 16: bSkipEmpty = TRUE; break; default: bSkipEmpty = FALSE; break; }
// Version stamp use class name as res id
if(lpResItem->lpszResID) strResName = lpResItem->lpszResID; else strResName = "";
dwItemID = lpResItem->dwItemID;
if(lpResItem->dwTypeID==5 && dwItemID==0 && lpResItem->dwExtStyle){ sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=0x%08x\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, ISEXTSTYLE, ST_TRANSLATED, strResName.GetBuffer(0), lpResItem->dwExtStyle); fileOut.WriteString(strToken); }
// Add font info for dialogs
if((theApp.IsFlag(CMainApp::FONTS) && (lpResItem->dwTypeID==5) && (dwItemID==0))) { if( (lpResItem->dwStyle & DS_SETFONT)!=DS_SETFONT ){ sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, ISDLGFONTNAME | ISDLGFONTSIZE, ST_TRANSLATED, strResName.GetBuffer(0));
WriteCon(CONWRN, "Dialog ID %s is missing the DS_SETFONT bit. Cannot extract font information!\r\n", strToken);
}else{ // Add font information
if (lpResItem->bCharSet != DEFAULT_CHARSET){ sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%s:%hd:%d\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, ISDLGFONTNAME | ISDLGFONTSIZE|ISDLGFONTCHARSET, ST_TRANSLATED, strResName.GetBuffer(0), Format(lpResItem->lpszFaceName), lpResItem->wPointSize, lpResItem->bCharSet);
}else{ sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%s:%hd\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, ISDLGFONTNAME | ISDLGFONTSIZE , ST_TRANSLATED, strResName.GetBuffer(0), Format(lpResItem->lpszFaceName), lpResItem->wPointSize); }
fileOut.WriteString(strToken); }
}
strCaption = lpResItem->lpszCaption;
// Set the flag
wFlag = 0;
if(!(bSkipEmpty && strCaption.IsEmpty())) { CString strExt; switch(lpResItem->dwTypeID) { case 2: case 3: case 23: case 240: case 1024: case 2110: case 2200: { switch(lpResItem->dwTypeID) { case 2: strExt = ".bmp"; break;
case 3: strExt = ".ico"; break;
case 240: case 1024: strExt = ".bin"; break;
case 23: case 2110: strExt = ""; break;
case 2200: strExt = ".inf"; break;
}
// create the output name
CString strOutputName; if(lpResItem->dwResID) { strOutputName = CreateName( strFileName, strExt, lpResItem->dwResID); } else { strOutputName = CreateName( strFileName, strExt, lpResItem->lpszResID); }
// Get the image from the file
DWORD dwBufSize = RSGetResImage( hModule, lpszType, lpszRes, dwLang, NULL, 0 );
BYTE * pBuf = (BYTE*)(new BYTE[dwBufSize]);
if(pBuf==NULL) { WriteCon(CONERR, "Warning: Failed to allocate buffer for image! (%d, %d, %s, Size: %d)\r\n", lpResItem->dwTypeID, lpResItem->dwResID, lpResItem->lpszResID, dwBufSize); break; }
dwBufSize = RSGetResImage( hModule, lpszType, lpszRes, dwLang, pBuf, dwBufSize );
// write the data in to a file
CFile OutputFile; if(!OutputFile.Open(strOutputDir+strOutputName, CFile::modeCreate | CFile::modeWrite)) { WriteCon(CONERR, "Cannot create file: %s\r\n", CalcTab(strOutputDir+strOutputName, strOutputName.GetLength()+strOutputDir.GetLength()+5, ' ')); delete pBuf; break; }
switch(lpResItem->dwTypeID) { case 2: { BITMAPFILEHEADER bmpFileHeader; BITMAPINFO * pbmpInfo = (BITMAPINFO *)pBuf; DWORD dwNumColor = 0; if(pbmpInfo->bmiHeader.biBitCount!=24) dwNumColor = ( 1L << pbmpInfo->bmiHeader.biBitCount);
bmpFileHeader.bfType = 0x4d42; bmpFileHeader.bfSize = (dwBufSize+sizeof(BITMAPFILEHEADER))/4; bmpFileHeader.bfReserved1 = 0; bmpFileHeader.bfReserved2 = 0; bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + pbmpInfo->bmiHeader.biSize + dwNumColor*sizeof(RGBQUAD);
OutputFile.Write(&bmpFileHeader, sizeof(BITMAPFILEHEADER)); } break; case 3: { ICONHEADER icoHeader; BITMAPINFOHEADER * pbmpInfoH = (BITMAPINFOHEADER*)pBuf;
icoHeader.idReserved = 0; icoHeader.idType = 1; icoHeader.idCount = 1; icoHeader.bWidth = LOBYTE(pbmpInfoH->biWidth); icoHeader.bHeight = LOBYTE(pbmpInfoH->biWidth); icoHeader.bColorCount = 16; icoHeader.bReserved = 0; icoHeader.wPlanes = 0; icoHeader.wBitCount = 0; icoHeader.dwBytesInRes = dwBufSize; icoHeader.dwImageOffset = sizeof(ICONHEADER);
OutputFile.Write(&icoHeader, sizeof(ICONHEADER)); } case 23: case 240: case 1024: case 2110: case 2200: { //
// No header for html stuff.
//
break; } break; default: break; }
OutputFile.Write(pBuf, dwBufSize);
OutputFile.Close(); delete pBuf;
strCaption = strOutputName; } break; case 4: if(lpResItem->dwFlags & MF_POPUP) { wFlag = ISPOPUP;
// check if this popup has a valid ID
if (LOWORD(dwItemID)==0xffff) wFlag |= OLD_POPUP_ID;
dwItemID = (LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID); } else if (LOWORD(dwItemID)==0xffff) { dwItemID = HIWORD(dwItemID); WriteCon (CONWRN, TEXT("Token [[%u|%u|%u|%u|%u|\"%s\"]] is generated with a suspicious ID. Please check the resource file for invalid ID's.\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, wFlag, ST_TRANSLATED, strResName.GetBuffer(0));
}
break; case 5: if(dwItemID==0) { wFlag = ISCAP; }
// check if this is a duplicated id
if (LOWORD(dwItemID)==0xffff) wFlag |= ISDUP;
dwItemID = (LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID); break; case 9: { CAccel accel(lpResItem->dwFlags, lpResItem->dwStyle); strCaption = accel.GetText();
// check if this is a duplicated ID
if(HIWORD(dwItemID)) { wFlag |= ISDUP; } } break; case 11: dwItemID = LOWORD(dwItemID); break; case 16: strResName = lpResItem->lpszClassName; break; default: break; }
// Create the token file
if(lpResItem->dwTypeID==11 && theApp.IsFlag(CMainApp::SPLIT)) { // Search for the \r\n and replace them
while((iPos = strCaption.Find("\r\n"))!=-1) { sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%s\\r\\n\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, wFlag | wMsgCount++, ST_TRANSLATED, strResName.GetBuffer(0), Format(strCaption.Left(iPos)));
strCaption = strCaption.Right(strCaption.GetLength()-2-iPos); fileOut.WriteString(strToken); } wMsgCount = 0; } else { if(lpResItem->dwTypeID==16 && theApp.IsFlag(CMainApp::NOVERSION) && (strResName==TEXT("FileVersion") || strResName==TEXT("ProductVersion") || strResName==TEXT("Platform"))){ //
// do not generate token for these resources
//
}else{ sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%s\n"), lpResItem->dwTypeID, lpResItem->dwResID, dwItemID, /*(LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID),*/ wFlag, ST_TRANSLATED, strResName.GetBuffer(0), Format(strCaption));
fileOut.WriteString(strToken); } }
// If this is a dialog box add the coordinates
if(lpResItem->dwTypeID==5) { sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%hu %hu %hu %hu\n"), lpResItem->dwTypeID, lpResItem->dwResID, (LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID), wFlag | ISCOR, ST_TRANSLATED, strResName.GetBuffer(0), lpResItem->wX, lpResItem->wY, lpResItem->wcX, lpResItem->wcY);
fileOut.WriteString(strToken);
//Extract STATIC control alignment style info
if (LOBYTE(lpResItem->wClassName) == 0x82 && theApp.IsFlag(CMainApp::ALIGNMENT)) {
CHAR szBuf[20]="SS_LEFT"; if ((lpResItem->dwStyle & SS_CENTER) == SS_CENTER) lstrcpy(szBuf, "SS_CENTER"); else if ((lpResItem->dwStyle & SS_RIGHT)==SS_RIGHT) lstrcpy(szBuf, "SS_RIGHT");
sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%s\n"), lpResItem->dwTypeID, lpResItem->dwResID, (LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID), wFlag | ISALIGN, ST_TRANSLATED, strResName.GetBuffer(0), szBuf);
fileOut.WriteString(strToken); } }
} else { // If this is a dialog box add the coordinates
if(lpResItem->dwTypeID==5) {
sprintf(strToken.GetBuffer(MAX_STR_SIZE), TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]=%hu %hu %hu %hu\n"), lpResItem->dwTypeID, lpResItem->dwResID, (LOWORD(dwItemID)==0xffff ? HIWORD(dwItemID) : dwItemID), wFlag | ISCOR, ST_TRANSLATED, strResName.GetBuffer(0), lpResItem->wX, lpResItem->wY, lpResItem->wcX, lpResItem->wcY);
fileOut.WriteString(strToken); } } } // end while
} } }
fileOut.Close();
// Check the size of the new file and remove it if empty...
CFileStatus fstat; if(CFile::GetStatus(m_strTgtTok, fstat)) if(fstat.m_size==0) CFile::Remove(m_strTgtTok);
WriteCon(CONBOTH, " %hu Items\r\n", wCount); if(bVersionStampOnly) { ReturnErr = ERR_FILE_VERSTAMPONLY; theApp.SetReturn(ERROR_FILE_VERSTAMPONLY); WriteCon(CONWRN, "%s : Version Stamping only!\r\n", strFileName); } if(bCustomResource) { SetReturn(ERROR_FILE_CUSTOMRES); WriteCon(CONWRN, "%s : Custom resource!\r\n", strFileName); } }
exit: RSCloseModule(hModule);
return ReturnErr; }
|