|
|
//#include <assert.h>
#include <ctype.h>
#include <malloc.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include <tchar.h>
#ifdef RLDOS
#include "dosdefs.h"
#else
#include <windows.h>
#include "windefs.h"
#endif
#include "restok.h"
#include "custres.h"
#include "ntmsgtbl.h"
#include "rlmsgtbl.h"
#include "resread.h"
#include "projdata.h"
//B_FormatMessage prototype
#include "showerrs.h"
#define SAME 0 //... Used in string comparisons
#define STRINGFILEINFO (TEXT("StringFileInfo"))
#define VARFILEINFO (TEXT("VarFileInfo"))
#define TRANSLATION (TEXT("Translation"))
#define LANGUAGEINFO (TEXT("Language Info"))
#define STRINGFILEINFOLEN (lstrlen( (TCHAR *)STRINGFILEINFO) + 1)
#define VARFILEINFOLEN (lstrlen( (TCHAR *)VARFILEINFO) + 1)
#define TRANSLATIONLEN (lstrlen( (TCHAR *)TRANSLATION) + 1)
#define LANGSTRINGLEN 8 //... # WCHARs in string denoting language
//... and code page in a Version resource.
#define TRANSDATALEN 2 //... # bytes in a Translation value
#define VERTYPEBINARY 0 //... Version data value is binary
#define VERTYPESTRING 1 //... Version data value is a string
#define VERMEM 2048 //... Fixed size of buffer for new version stamp
//... Decrement WORD at *pw by given amount w
#define DECWORDBY( pw,w) if (pw) { *(pw) = (*(pw) > (w)) ? *(pw) - (w) : 0;}
//... Increment WORD at *pw by given amount w
#define INCWORDBY( pw,w) if (pw) { *(pw) += (w);}
//... How many BYTES in the given string?
#define BYTESINSTRING(s) (lstrlen( (TCHAR *)s) * sizeof( TCHAR))
//... Dialog box controls (from RC.H)
#define BUTTON 0x80
#define EDIT 0x81
#define STATIC 0x82
PVERBLOCK MoveAlongVer( PVERBLOCK, WORD *, WORD *, WORD *); BOOL FilterRes( WORD, RESHEADER *); TCHAR *GetVerValue( PVERBLOCK); void PutNameOrd( FILE *, BOOL, WORD , TCHAR *, DWORD *); void GetNameOrd( FILE *, BOOL UNALIGNED*, WORD UNALIGNED*, TCHAR *UNALIGNED*, DWORD *); void CopyRes( FILE *fpInResFile, FILE *fpOutResFile, RESHEADER *pResHeader, fpos_t *pResSizePos);
BOOL fInThirdPartyEditer = FALSE;//.. Are we in a 3rd-party resource editor?
BOOL fInQuikEd = FALSE; //... Are we in RLQuiked? (see rlquiked.c)
BOOL gfShowClass = FALSE; //... Set TRUE to put dlg box elemnt class
//... in token file
#if defined(DBCS)
BOOL gfExtendedTok = TRUE; //... Set TRUE if -x is choosen
#else
BOOL gfExtendedTok = FALSE; //... Set TRUE if -x is choosen
#endif
#ifdef _DEBUG
extern PMEMLIST pMemList; #endif
#ifdef RLRES32
#ifndef CAIRO
extern VOID *pResMsgData; // NT-specific Message Table resource
#endif //RLRES32
#endif //CAIRO
extern BOOL gbMaster; //... TRUE if we are working on a Master Project
extern BOOL gfReplace; //... FALSE if appending new language to existing resources
extern BOOL gbShowWarnings; //... Display warnining messages if TRUE
extern UCHAR szDHW[];
extern char * gszTmpPrefix;
MSTRDATA gMstr = //... Data from Master Project file (MPJ)
{ //... Fields filled in main (UI)
"", "", "", "", "", MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), CP_ACP //... System default Windows code page
};
PROJDATA gProj = //... Data from Project file (PRJ)
{ //... Fields filled in main (UI)
"", "", "", "", "", "", CP_ACP, //... System default Windows code page
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), FALSE, FALSE };
/**
* Function: ReadWinRes * * The main resource Read/Writer function to process the resource file to be * localzied. * * ReadWinRes reads the resource header to determine the current resource type, * then executes the corresponding Get/Put resource functions to extract and * insert localized information contained in the resource file. ReadWinRes, is * excuted in two modes, Tokenize, and Generate. During Tokenize mode, * ReadWinRes writes all the localized information contained in the resouce to * a token file. During Generate mode, ReadWinRes, replaces all the localized * information in the input resource file, with the corresponding information * in the token file to gernerate a localized resource file. * * Currently the following resouce types are supported. * * Version Stamping. * Menus. * Dialogs. * Accelerators. * String Tables. * Version Stamps * Message Tables (NT) * * Arguments: * * InResFile, Handle to binary input resource file. * OutFesFile, Handle to binary output resouce file. Not used during tokenize * mode. * TokFile, Handle to text token file. * BOOL, flag to indicate whether to build output resource file. * BOOL, flag to indicate whether to build token file. * * * Returns: * ??? * * Errors Codes: * ??? * * History: * 10/91 Added Version stamping support. TerryRu * 11/91, Completed Version stamping support. TerryRu * * **/
int ReadWinRes(
FILE *InResFile, FILE *OutResFile, FILE *TokFile, BOOL fBuildRes, BOOL fBuildTok, WORD wFilter) { BOOL fDoAccel = TRUE; // set FALSE to not build accelerators
MENUHEADER *pMenuHdr = NULL; // Linked list of Menu info.
static RESHEADER ResHeader; // Structure contain Resource Header info.
VERBLOCK *pVerBlk = NULL; // Memory block containing Version Stamping String File Block,
static VERHEAD VerHdr; // Memory block containing Version Stamping Header info
DIALOGHEADER *pDialogHdr = NULL; // Linked list of Dialog info
STRINGHEADER *pStrHdr = NULL; // Array of String Tables.
ACCELTABLEENTRY *pAccelTable = NULL;// Array of Accelerator Keys
WORD wcTableEntries = 0; // Number of Accelerator tables
fpos_t ResSizePos = 0; // Position of lSize field in the
// Resource Header, used to fixup
// the Header once the size of the
// localized information is determined.
CUSTOM_RESOURCE *pCustomResource = NULL; LONG lEndOffset = 0L;
//... How large is the res file?
fseek( InResFile, 0L, SEEK_END); lEndOffset = ftell( InResFile);
rewind( InResFile);
//... process until end of input file
while ( ! feof( InResFile) ) { LONG lCurrOffset = 0L;
lCurrOffset = (LONG)ftell( InResFile);
if ( (lCurrOffset + (LONG)sizeof( RESHEADER)) >= lEndOffset ) { return 0; }
if ( GetResHeader( InResFile, &ResHeader, (DWORD *) NULL) == -1 ) { return (1); } //... Is this the dummy, res32-identifying, res?
if ( ResHeader.lSize == 0L ) { //... Yes, we so simply copy the header if we
//... are building a res file.
if ( fBuildRes ) { CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos); }
#ifdef RLRES32
else { if ( gbShowWarnings && OutResFile && ftell( OutResFile) != 0L ) { lstrcpyA( szDHW, "type");
if ( ResHeader.wTypeID == IDFLAG ) { sprintf( &szDHW[ lstrlenA( szDHW)], " \"%s\"", ResHeader.pszType); } else { sprintf( &szDHW[ lstrlenA( szDHW)], " %hu,", ResHeader.wTypeID); } strcat( szDHW, " name");
if ( ResHeader.wNameID == IDFLAG ) { sprintf( &szDHW[ lstrlenA( szDHW)], " \"%s\"", ResHeader.pszName); } else { sprintf( &szDHW[ lstrlenA( szDHW)], " %hu,", ResHeader.wNameID); } sprintf( &szDHW[ lstrlenA( szDHW)], " pri-lang %#hx sub-lang %#hx", PRIMARYLANGID( ResHeader.wLanguageId), SUBLANGID( ResHeader.wLanguageId));
ShowEngineErr( IDS_ZERO_LEN_RES, szDHW, NULL); } DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL);
if (OutResFile != NULL) { DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), NULL); } } #endif
ClearResHeader( ResHeader); continue; //... Ship this dummy header
} //... Check to see if we want to filter out this
//... resource type.
if ( FilterRes( wFilter, &ResHeader) ) { //... skip this resource type
SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL);
#endif
ClearResHeader( ResHeader); continue; }
if ( fBuildTok ) { if ( ResHeader.wLanguageId != (fInThirdPartyEditer ? gProj.wLanguageID : gMstr.wLanguageID) ) { //... Skip this resource (wrong lanugage)
if ( gbShowWarnings ) { lstrcpyA( szDHW, "type");
if ( ResHeader.wTypeID == IDFLAG ) { sprintf( &szDHW[ lstrlenA( szDHW)], " \"%s\"", ResHeader.pszType); } else { sprintf( &szDHW[ lstrlenA( szDHW)], " %u,", ResHeader.wTypeID); } strcat( szDHW, " name");
if ( ResHeader.wNameID == IDFLAG ) { sprintf( &szDHW[ lstrlenA( szDHW)], " \"%s\"", ResHeader.pszName); } else { sprintf( &szDHW[ lstrlenA( szDHW)], " %u,", ResHeader.wNameID); } sprintf( &szDHW[ lstrlenA( szDHW)], " pri-lang %#x sub-lang %#x", PRIMARYLANGID( ResHeader.wLanguageId), SUBLANGID( ResHeader.wLanguageId));
ShowEngineErr( IDS_SKIP_RES, LongToPtr(ResHeader.lSize), szDHW); } SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), NULL);
#endif
ClearResHeader( ResHeader); continue; } } else if ( fBuildRes ) { if ( gfReplace ) { if ( ResHeader.wLanguageId == gMstr.wLanguageID ) { ResHeader.wLanguageId = gProj.wLanguageID; } else { //... Copy this resource
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos); ClearResHeader( ResHeader); continue; } } else { //... ! gfReplace
if ( ResHeader.wLanguageId == gMstr.wLanguageID ) { fpos_t lFilePos = 0L; DWORD lTmpSize = 0L;
lFilePos = ftell( InResFile); //... Save file position
lTmpSize = ResHeader.lSize; //... and resource size
//... Duplicate this resource
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos); fseek( InResFile, (long)lFilePos, SEEK_SET); ResHeader.wLanguageId = gProj.wLanguageID; ResHeader.lSize = lTmpSize; } else { //... Simply copy this resource if not target language
if ( ResHeader.wLanguageId == gProj.wLanguageID ) { SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL); #endif
} else { CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos); } ClearResHeader( ResHeader); continue; } } }
switch ( ResHeader.wTypeID ) { case ID_RT_ACCELERATORS:
pAccelTable = GetAccelTable(InResFile, &wcTableEntries, (DWORD *)&ResHeader.lSize); if (fBuildTok) { TokAccelTable(TokFile, ResHeader, pAccelTable, wcTableEntries); }
if (fBuildRes) { PutAccelTable(OutResFile, TokFile, ResHeader, pAccelTable, wcTableEntries); }
ClearAccelTable (pAccelTable , wcTableEntries); break;
case ID_RT_DIALOG:
pDialogHdr = GetDialog(InResFile, (DWORD *)&ResHeader.lSize);
if (fBuildTok == TRUE) { TokDialog(TokFile, ResHeader, pDialogHdr); }
if (fBuildRes == TRUE) { PutDialog(OutResFile, TokFile, ResHeader, pDialogHdr); } ClearDialog (pDialogHdr);
break;
case ID_RT_DLGINIT: { PDLGINITDATA pDlgInit = GetDlgInit( InResFile, (DWORD *)&ResHeader.lSize);
if ( fBuildTok ) { TokDlgInit( TokFile, ResHeader, pDlgInit); }
if ( fBuildRes ) { PutDlgInit( OutResFile, TokFile, ResHeader, pDlgInit); } ClearDlgInitData( pDlgInit); break; } case ID_RT_MENU: // allocate space for a new header
pMenuHdr = (MENUHEADER *)FALLOC( sizeof( MENUHEADER)); GetResMenu(InResFile, (DWORD *)&ResHeader.lSize, pMenuHdr);
if (fBuildTok == TRUE) { TokMenu(TokFile, ResHeader, pMenuHdr); }
if (fBuildRes == TRUE) { PutMenu(OutResFile, TokFile, ResHeader, pMenuHdr); }
ClearMenu(pMenuHdr);
break;
case ID_RT_STRING:
pStrHdr = GetString(InResFile, (DWORD *)&ResHeader.lSize);
if (fBuildTok == TRUE) { TokString(TokFile, ResHeader, pStrHdr); }
if (fBuildRes == TRUE) { PutStrHdr(OutResFile, TokFile, ResHeader, pStrHdr); }
ClearString(pStrHdr);
break;
#ifdef RLRES32
#ifndef CAIRO
// we currently only do Error tables under NT,
// under CAIRO we ignore them
case ID_RT_ERRTABLE: //... NT-specific Message Table resource
pResMsgData = GetResMessage(InResFile, (DWORD *)&ResHeader.lSize);
if (! pResMsgData) { QuitT( IDS_ENGERR_13, (LPTSTR)IDS_MSGRESTBL, NULL); }
if (fBuildTok == TRUE) { TokResMessage(TokFile, ResHeader, pResMsgData); }
if (fBuildRes == TRUE) { PutResMessage(OutResFile, TokFile, ResHeader, pResMsgData); }
ClearResMsg( &pResMsgData);
break; #endif
#endif
#ifndef CAIRO
case ID_RT_VERSION: { WORD wRead = 0;
wRead = GetResVer(InResFile, (DWORD *)&ResHeader.lSize, &VerHdr, &pVerBlk);
#ifdef RLRES32
if (wRead == (WORD)-1) #else
if (wRead == FALSE) #endif
{ QuitT( IDS_ENGERR_14, (LPTSTR)IDS_VERBLOCK, NULL); }
// Building Tok file ?
// but only tokenize it if it contains a Version Block
if ( pVerBlk && fBuildTok == TRUE ) { #ifdef RLRES32
TokResVer( TokFile, ResHeader, pVerBlk, wRead); #else
TokResVer( TokFile, ResHeader, pVerBlk); #endif
}
// Building Res file ?
if ( fBuildRes == TRUE ) { PutResVer( OutResFile, TokFile, ResHeader,&VerHdr, pVerBlk); } RLFREE( pVerBlk); } break; #else
case ID_RT_VERSION: #endif
case ID_RT_CURSOR: case ID_RT_BITMAP: case ID_RT_ICON: case ID_RT_FONTDIR: case ID_RT_FONT: case ID_RT_RCDATA: #ifndef RLRES32
case ID_RT_ERRTABLE: //... NT-specific Message Table resourc
#endif
case ID_RT_GROUP_CURSOR: case ID_RT_GROUP_ICON: case ID_RT_NAMETABLE: default:
if (GetCustomResource(InResFile, (DWORD *)&ResHeader.lSize, &pCustomResource, ResHeader)) { // Non localized resource type, skip or copy it
if (fBuildTok == TRUE) { if ( gbShowWarnings && ( ResHeader.wTypeID == ID_RT_RCDATA || ResHeader.wTypeID > 16) ) { static CHAR szType[256]; static CHAR szName[256];
if ( ResHeader.bTypeFlag == IDFLAG ) sprintf( szType, "%u", ResHeader.wTypeID); else { _WCSTOMBS( &szType[1], ResHeader.pszType, sizeof( szType), (UINT)-1); szType[0] = '\"'; szType[ lstrlenA( szType)] = '\"'; }
if ( ResHeader.bNameFlag == IDFLAG ) sprintf( szName, "%u", ResHeader.wNameID); else { _WCSTOMBS( &szName[1], ResHeader.pszName, sizeof( szName), (UINT)-1); szName[0] = '\"'; szName[ lstrlenA( szName)] = '\"'; } ShowEngineErr( IDS_UNK_CUST_RES, (void *)szType, (void *)szName); } SkipBytes(InResFile, (DWORD *)&ResHeader.lSize); } else if ( fBuildRes ) { CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos); } } else { if (fBuildTok == TRUE) { TokCustomResource(TokFile, ResHeader, &pCustomResource); }
if (fBuildRes == TRUE) { PutCustomResource(OutResFile, TokFile, ResHeader, &pCustomResource); } ClearCustomResource(&pCustomResource); }
#ifdef RLRES32
DWordUpFilePointer(InResFile, MYREAD, ftell(InResFile), NULL);
if (OutResFile != NULL) { DWordUpFilePointer(OutResFile, MYWRITE, ftell(OutResFile), NULL); } #endif
break; } //... END SWITCH
#ifndef RLRES32
// skip any extra bytes (Win 3.1 exes have
// alot of extra stuff!).
// No extra stuff in res extracted from NT exes
SkipBytes(InResFile, (DWORD *)&ResHeader.lSize); #endif
ClearResHeader(ResHeader);
#ifdef RLRES32
DWordUpFilePointer(InResFile, MYREAD, ftell(InResFile), NULL);
if (OutResFile != NULL) { DWordUpFilePointer(OutResFile, MYWRITE, ftell(OutResFile), NULL); } #endif
} // END while ( ! feof( InResFile)
return 0; }
/**
* * * Function:ClearAccelTable * Removes the accelerator table array from memory. * * Arguments: * pAccelTable, pointer to arary of accelerators * wctablesEntries, number of accelerators in arrary * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, Implemented Terryru * * **/
void ClearAccelTable(ACCELTABLEENTRY *pAccelTable, WORD wcTableEntries) { RLFREE( pAccelTable); }
/**
* * * Function: ClearDialog * Remove Dialog defintions from memory. * * Arguments: * pDilaogHdr, Linked list of dialog information. * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, Implemented TerryRu * * **/
void ClearDialog (DIALOGHEADER * pDialogHdr) { BYTE i;
for (i = 0; i < (BYTE) pDialogHdr->wNumberOfItems; i ++) { if (pDialogHdr->pCntlData[i].pszClass) { RLFREE( pDialogHdr->pCntlData[i].pszClass); }
if ( pDialogHdr->pCntlData[i].pExtraStuff ) { RLFREE( pDialogHdr->pCntlData[i].pExtraStuff ); }
RLFREE( pDialogHdr->pCntlData[i].pszDlgText); } // now RLFREE fields in dialog header
RLFREE( pDialogHdr->pszDlgClass); RLFREE( pDialogHdr->pszFontName); RLFREE( pDialogHdr->pszDlgMenu); RLFREE( pDialogHdr->pszCaption); RLFREE( pDialogHdr->pCntlData);
// and finally clear header
RLFREE( pDialogHdr); }
/**
* * * Function: ClearMenu * Removes Menu defintions from memory. * * Arguments: * pMenuHdr, linked list of Menu info * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, Implemented. TerryRu * * **/
void ClearMenu(MENUHEADER *pMenuHdr) { MENUITEM *pMenuItem; MENUITEM *pMenuHead;
pMenuItem = pMenuHead = pMenuHdr->pMenuItem;
// remove all the menu items from the list
while (pMenuItem) { pMenuItem = pMenuHead->pNextItem; RLFREE( pMenuHead->szItemText); RLFREE( pMenuHead); pMenuHead = pMenuItem; }
// now remove the menuheader
if (pMenuHdr->pExtraStuff) RLFREE( pMenuHdr->pExtraStuff );
RLFREE( pMenuHdr); }
/**
* * * Function: ClearResHeader * Remove resheader name, and type fields from memory. * * Arguments: * ResHdr, structure containing resheader info. * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, Implemented TerryRu. * * **/
void ClearResHeader(RESHEADER ResHdr) { RLFREE( ResHdr.pszType); RLFREE( ResHdr.pszName); }
/**
* * * Function: ClearString * Removes the StringTable Defintions from memory. * * Arguments: * pStrHdr, pointer to array of 16 string tables. * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, Implemented. TerryRu * * **/
void ClearString( STRINGHEADER *pStrHdr) { BYTE i;
for (i = 0; i < 16; i++) { RLFREE( pStrHdr->pszStrings[i]); } RLFREE( pStrHdr); }
/**
* * * Function: quit * quit, Error Handling routine used to display error code and terminate program * * Arguments: * error, number of error. * pszError, descriptive error message. * * Returns: * NA. * * Errors Codes: * * * History: * 7/91, Implemented TerryRu * 10/91, Hacked to work under windows TerryRu * ??? Need to add better win/dos support * **/
void QuitA( int error, LPSTR pszArg1, LPSTR pszArg2) { char szErrStr1[2048] = "*?*"; char szErrStr2[2048] = "*?*"; char *psz1 = pszArg1; char *psz2 = pszArg2;
//... clean up after error and exit,
//... returning error code
_fcloseall();
if ( pszArg1 != NULL && pszArg1 <= (LPSTR)0x0000ffff ) {
B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78) | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, NULL, (DWORD)(DWORD_PTR)pszArg1, szErrStr1, sizeof( szErrStr1), NULL); psz1 = szErrStr1; }
if ( pszArg2 != NULL && pszArg2 < (LPSTR)0x0000ffff ) {
B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78) | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, NULL, (DWORD)(DWORD_PTR)pszArg2, szErrStr2, sizeof( szErrStr2), NULL); psz2 = szErrStr2; } ShowEngineErr( error, psz1, psz2); FreeLangList();
#ifdef _DEBUG
FreeMemList( NULL); #endif // _DEBUG
DoExit( (error == 4) ? 0 : error); }
#ifdef UNICODE
/* Handles errors, in UNICODE environments*/
LPSTR MakeMBMsgW(
LPWSTR pszArg, //... Msg ID# or msg text
LPSTR szBuf, //... Buffer for converted msg
USHORT usBufLen) //... #bytes in szBuf
{ char *pszRet = NULL;
if ( pszArg ) { if ( pszArg >= (LPTSTR)0x0400 ) { _WCSTOMBS( szBuf, (WCHAR *)pszArg, usBufLen, lstrlen( pszArg ) + 1 ); } else { B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78) | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, NULL, (DWORD)(DWORD_PTR)pszArg, szBuf, usBufLen, NULL); } pszRet = szBuf; } return ( pszRet); }
//...............................................................
void QuitW( int error, LPWSTR pszArg1, LPWSTR pszArg2) { char szErrStr1[2048] = "*?*"; char szErrStr2[2048] = "*?*";
QuitA( error, MakeMBMsgW( pszArg1, szErrStr1, sizeof( szErrStr1)), MakeMBMsgW( pszArg2, szErrStr2, sizeof( szErrStr2))); }
#endif
/**
* * * Function: GetAccelTable, * Reads the Accelerator key defintions from the resource file * * Arguments: * InResFile, Handle to Resource file. * pwcTableEntries, pointer to an array of accelerator key defintions. * plSize, address of size of Resource. * * Returns: * pwcTableEntries containing all the key defintions. * * Errors Codes: * * History: * 8/91 Implemented TerryRu * 4/92 Added RLRES32 support TerryRu * * * **/
ACCELTABLEENTRY * GetAccelTable(FILE *InResFile, WORD *pwcTableEntries, DWORD *plSize) { ACCELTABLEENTRY *pAccelTable; BOOL quit = FALSE;
// need to use sizeof operator in memory
// allocation because of structure packing.
*pwcTableEntries = (WORD) 0;
pAccelTable = (ACCELTABLEENTRY *) FALLOC( ((WORD)*plSize * sizeof( WORD)));
while (*plSize && !quit) {
#ifdef RLRES32
pAccelTable[ *pwcTableEntries].fFlags = (WORD) GetWord( InResFile, plSize); #else
pAccelTable[ *pwcTableEntries].fFlags = (BYTE) GetByte( InResFile, plSize); #endif
pAccelTable[*pwcTableEntries].wAscii = GetWord (InResFile, plSize); pAccelTable[*pwcTableEntries].wID = GetWord (InResFile, plSize);
#ifdef RLRES32
pAccelTable[ *pwcTableEntries].wPadding = GetWord( InResFile, plSize); #endif
if ( pAccelTable[ *pwcTableEntries].fFlags & HIBITVALUE ) { quit = TRUE; } ++*pwcTableEntries; }
if ( (long)*plSize <= 0 ) { *plSize = 0; } return pAccelTable; }
/**
* * * Function: GetDialog, * Reads the dialog defintions from the res file, and places the info * into a linked list. * * * Arguments: * InResFile, Handle to input resource handle, posistioned to begining * of dialog defintion. * plSize, pointer to size in bytes of the dialog information. * * Returns: * pointer to DIALOGHEADER type containing the dialog information, * * * Errors Codes: * None ??? * * History: * 12/91, Cleaned up comments. TerryRu * 04/92, Added RLRES32 support. TerryRu * * **/
DIALOGHEADER *GetDialog( FILE *InResFile, DWORD * plSize) { DIALOGHEADER *pDialogHdr; TCHAR *UNALIGNED*ptr; WORD i; LONG lStartingOffset; static TCHAR szBuf[ 255]; LONG lExtra; WORD j;
lStartingOffset = ftell(InResFile);
pDialogHdr = (DIALOGHEADER *)FALLOC( sizeof( DIALOGHEADER));
// lstyle
pDialogHdr->lStyle = GetdWord(InResFile, plSize);
#ifdef RLRES32
pDialogHdr->fDialogEx = (HIWORD(pDialogHdr->lStyle)==0xffff);
if (pDialogHdr->fDialogEx) { pDialogHdr->wDlgVer = LOWORD(pDialogHdr->lStyle); pDialogHdr->wSignature = HIWORD(pDialogHdr->lStyle); pDialogHdr->dwHelpID = GetdWord(InResFile, plSize); pDialogHdr->lExtendedStyle = GetdWord(InResFile, plSize); pDialogHdr->lStyle = GetdWord(InResFile, plSize); } else { pDialogHdr->lExtendedStyle = GetdWord(InResFile, plSize); }
pDialogHdr->wNumberOfItems = GetWord(InResFile, plSize); #else
pDialogHdr->wNumberOfItems = (BYTE) GetByte(InResFile, plSize); #endif
// allocate space to hold wNumberOfItems of pointers
// to Control Data structures
pDialogHdr->pCntlData = (CONTROLDATA *) FALLOC( pDialogHdr->wNumberOfItems * sizeof( CONTROLDATA));
// read x, y, cx, cy dialog cordinates
pDialogHdr->x = GetWord(InResFile, plSize); pDialogHdr->y = GetWord(InResFile, plSize); pDialogHdr->cx = GetWord(InResFile, plSize); pDialogHdr->cy = GetWord(InResFile, plSize);
//... Dialog Menu Name
GetNameOrd( InResFile, (BOOL UNALIGNED *)&pDialogHdr->bMenuFlag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->wDlgMenuID, (TCHAR *UNALIGNED*)&pDialogHdr->pszDlgMenu, plSize);
//... Dialog Class Name
GetNameOrd( InResFile, (BOOL UNALIGNED *)&pDialogHdr->bClassFlag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->wDlgClassID, (TCHAR *UNALIGNED*)&pDialogHdr->pszDlgClass, plSize);
// Dialog caption name
GetName( InResFile, szBuf, plSize); ptr = (TCHAR *UNALIGNED*)&pDialogHdr->pszCaption; AllocateName( *ptr, szBuf); lstrcpy( (TCHAR *)*ptr, (TCHAR *)szBuf);
// does dialog define a font.
if ( pDialogHdr->lStyle & DS_SETFONT ) { // extract this info.
pDialogHdr->wPointSize = GetWord( InResFile, plSize); if (pDialogHdr->fDialogEx) { pDialogHdr->wWeight = GetWord( InResFile, plSize); pDialogHdr->wItalic = GetWord( InResFile, plSize); } GetName( InResFile, szBuf, plSize); ptr = (TCHAR *UNALIGNED*)&pDialogHdr->pszFontName; AllocateName(*ptr, szBuf);
lstrcpy( (TCHAR *)*ptr, (TCHAR *)szBuf);
} else { pDialogHdr->pszFontName = (TCHAR*)FALLOC( 0); }
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), plSize);
#endif
//... read each dialog control
for (i = 0; i < pDialogHdr->wNumberOfItems ; i++) {
#ifdef RLRES32
if (pDialogHdr->fDialogEx) { pDialogHdr->pCntlData[i].dwHelpID = GetdWord(InResFile, plSize); pDialogHdr->pCntlData[i].lExtendedStyle = GetdWord(InResFile, plSize); pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize); } else { pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize); pDialogHdr->pCntlData[i].lExtendedStyle = GetdWord(InResFile, plSize); }
#endif // RLRES32
pDialogHdr->pCntlData[i].x = GetWord(InResFile, plSize); pDialogHdr->pCntlData[i].y = GetWord(InResFile, plSize); pDialogHdr->pCntlData[i].cx = GetWord(InResFile, plSize); pDialogHdr->pCntlData[i].cy = GetWord(InResFile, plSize);
// wId
if (pDialogHdr->fDialogEx) pDialogHdr->pCntlData[i].dwID = GetdWord (InResFile, plSize); else pDialogHdr->pCntlData[i].dwID = (DWORD)GetWord (InResFile, plSize);
#ifdef RLRES16
// lStyle
pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize);
pDialogHdr->pCntlData[i].bClass = (BYTE) GetByte(InResFile, plSize);
// does dialog have a class?
if (!(pDialogHdr->pCntlData[i].bClass & 0x80)) { GetName(InResFile, szBuf, plSize); ptr = &pDialogHdr->pCntlData[i].pszClass; AllocateName(*ptr, szBuf); lstrcpy ((TCHAR *)*ptr, (TCHAR *)szBuf); } else { pDialogHdr->pCntlData[i].pszClass = NULL; }
#else
GetNameOrd (InResFile, (BOOL UNALIGNED *)&pDialogHdr->pCntlData[i].bClass_Flag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->pCntlData[i].bClass, (TCHAR *UNALIGNED*)&pDialogHdr->pCntlData[i].pszClass, plSize);
#endif
GetNameOrd (InResFile, (BOOL UNALIGNED *)&pDialogHdr->pCntlData[i].bID_Flag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->pCntlData[i].wDlgTextID, (TCHAR *UNALIGNED*)&pDialogHdr->pCntlData[i].pszDlgText, plSize);
#ifdef RLRES16
pDialogHdr->pCntlData[i].unDefined = (BYTE) GetByte(InResFile, plSize);
#else
pDialogHdr->pCntlData[i].wExtraStuff = (WORD) GetWord(InResFile, plSize); if (pDialogHdr->fDialogEx && pDialogHdr->pCntlData[i].wExtraStuff) { lExtra = pDialogHdr->pCntlData[i].wExtraStuff; j = 0; pDialogHdr->pCntlData[i].pExtraStuff = (BYTE *)FALLOC( pDialogHdr->pCntlData[i].wExtraStuff ); while ( lExtra-- ) pDialogHdr->pCntlData[i].pExtraStuff[j++] = GetByte( InResFile, plSize ); } else pDialogHdr->pCntlData[i].pExtraStuff = NULL;
#endif // RLRES16
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), plSize);
#endif // RLRES32
}
// watch for overflow of plsize
if ((long) *plSize <= 0) { *plSize = 0; } return (pDialogHdr); }
/**
* * * Function: GetResMenu, * Reads the Menu defintions from the resrouce file, and insert the info * into a linked list.. * * Arguments: * InResFile, Input res handle, positioned at being of Menu Definition. * lSize, pointer to size of Menu Defintion. * pMenuHeader, pointer to structure to contain menu info. * * Returns: * pMenuHeader containing linkd list of Menu info. * * Errors Codes: * None. * * History: * 7/91, implemented Terryru * 12/91, cleaned up comments Terryru * 4/92, Added PDK2 support Terryru * 4/92, Added RLRES32 support Terryru * **/
void GetResMenu(FILE *InResFile, DWORD *lSize , MENUHEADER *pMenuHeader) { static TCHAR szItemText[255]; BOOL fStart = TRUE; BOOL fQuit = FALSE; LONG lExtra = 0; WORD i = 0; WORD wPopItems = 0, wMenuID = 0; MENUITEM * pcMenuItem; TCHAR *UNALIGNED*ptr; WORD wNestingLevel = 0; WORD wFlags; LONG lStartingOffset; // used to dword align file
lStartingOffset = ftell(InResFile);
pMenuHeader->wVersion = GetWord(InResFile, lSize); pMenuHeader->cbHeaderSize = GetWord(InResFile, lSize);
pMenuHeader->fMenuEx = (pMenuHeader->wVersion == 1);
if (pMenuHeader->fMenuEx && pMenuHeader->cbHeaderSize) { lExtra = pMenuHeader->cbHeaderSize; pMenuHeader->pExtraStuff = (BYTE *)FALLOC( pMenuHeader->cbHeaderSize ); while ( lExtra-- ) pMenuHeader->pExtraStuff[i++] = GetByte( InResFile, lSize); } else pMenuHeader->pExtraStuff = NULL;
// add all the items to the list
while ( (((signed long) *lSize) >= 0) && !fQuit) { if (fStart) { // start the menu item list
pcMenuItem = pMenuHeader->pMenuItem = (MENUITEM *)FALLOC( sizeof( MENUITEM)); pcMenuItem->pNextItem = NULL; fStart = FALSE; } else { // add space to the menu list
// allocate space for next Item
pcMenuItem->pNextItem = (MENUITEM *)FALLOC (sizeof( MENUITEM));
pcMenuItem = pcMenuItem->pNextItem; pcMenuItem->pNextItem = NULL;
}
if (pMenuHeader->fMenuEx) { pcMenuItem->dwType = GetdWord( InResFile, lSize); pcMenuItem->dwState = GetdWord( InResFile, lSize); pcMenuItem->dwMenuID = GetdWord( InResFile, lSize);
pcMenuItem->fItemFlags = wFlags = GetWord(InResFile,lSize); // read type of menu item
if ( (wFlags & MFR_POPUP) ) { wFlags &= ~MFR_POPUP; // Normalize the menu
wFlags |= MF_POPUP; } //pcMenuItem->fItemFlags = wFlags;
} else { wFlags = GetWord(InResFile,lSize); // read type of menu item
pcMenuItem->fItemFlags = wFlags;
// is it a popup?
if ( ! (pcMenuItem->fItemFlags & POPUP) ) { pcMenuItem->dwMenuID = (DWORD)GetWord( InResFile, lSize); } }
GetName( InResFile, szItemText, lSize);
ptr = (TCHAR *UNALIGNED*)&pcMenuItem->szItemText; * ptr = (TCHAR *)FALLOC( MEMSIZE( lstrlen( szItemText) + 1));
lstrcpy( (TCHAR *)*ptr, (TCHAR *)szItemText);
if (pMenuHeader->fMenuEx) { DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), lSize);
if ( (wFlags & POPUP) ) { pcMenuItem->dwHelpID = GetdWord( InResFile, lSize); } }
if (wFlags & POPUP) { ++wNestingLevel; }
if (wFlags & ENDMENU) { if (wNestingLevel) { --wNestingLevel; } else { fQuit = TRUE; } } }
#ifdef RLRES32
WordUpFilePointer( InResFile, MYREAD, lStartingOffset, ftell( InResFile), lSize); #endif
}
int MyEOF(FILE *fPtr) { #ifdef RLRES32
LONG lCurOffset; LONG lEndOffset;
lCurOffset = ftell(fPtr); lEndOffset = fseek(fPtr, SEEK_END, 0);
// reset file pointer
fseek( fPtr, lCurOffset, SEEK_SET);
return ((lEndOffset - lCurOffset) < sizeof (DWORD)); #else
return ( feof(fPtr)); #endif
}
void WordUpFilePointer(FILE *fPtr, BOOL bMode, LONG lStartingOffset, LONG lCurrentOffset , LONG *plPos) {
LONG lDelta; LONG lOffset; char buffer[]="\0\0\0\0\0\0\0\0";
lDelta = lCurrentOffset - lStartingOffset ; lOffset = WORDUPOFFSET( lDelta);
if ( bMode == MYREAD ) { fseek( fPtr, lOffset , SEEK_CUR); *plPos -= lOffset; } else { fwrite( buffer, 1, (size_t) lOffset, fPtr); *plPos += lOffset; } }
void DWordUpFilePointer(
FILE *fPtr, BOOL bMode, LONG lCurrentOffset, DWORD *plPos) //... New file position
{ LONG lOffset;
lOffset = DWORDUPOFFSET( lCurrentOffset);
if ( bMode == MYREAD ) { fseek( fPtr, lOffset, SEEK_CUR);
if ( plPos != NULL ) { *plPos -= lOffset; } } else { char buffer[]="\0\0\0\0\0\0\0";
fwrite( buffer, 1, (size_t)lOffset, fPtr);
if ( plPos != NULL ) { *plPos += lOffset; } } }
//
// Function: FilterRes, Public
//
// Synopsis: Determine whether the resource type is to be filtered
// The non filtered resource are OR together, thus several
// resource types can pass through the filter. Zero indicates
// no resources are to be filterd, 0xFFFF indicates to not filter
// custom resource.
//
//
// Arguments: [wFilter] Indicates the resources which we are to pass thru.
// [pRes] Ptr to Resource header struct
//
//
// Effects:
//
// Returns: TRUE Skip the current resource
// FALSE Use the current resource
//
// Modifies:
//
// History:
// 18-Oct-92 Created TerryRu
//
//
// Notes:
//
BOOL FilterRes( WORD wFilter, RESHEADER *pRes) { WORD wCurRes;
wCurRes = pRes->wTypeID;
if ( wFilter == 0 ) { return ( FALSE); }
if ( wCurRes == 0 ) { return ( FALSE); }
// check for special case for custom resources
if ( wFilter == (WORD)0xFFFF ) { if ( wCurRes > 16) { return ( FALSE); } else { return ( TRUE); } }
return ( ! (wFilter == wCurRes)); }
/**
* * * Function: GetResVer * * Extracts the version stamping information that * requires loclization from the resource file. The resource * information is containd is a USER defined resource * (ID = 16, Type = 1). * * The resource block format: * WORD wTotLen * WORD wValLen * BYTE szKey * BYTE szVal * * All information in the version stampling is contained in * repeating patters of this block type. All Key, and Value * fields are padded to start on DWORD boundaries. The * padding necessary to allign the blocks is not included in * the wTotLen field, but the padding to allign the fields inside * the block is. * * The following information in the Resource block needs to be * tokenized: * * * Key Field in StringFileInfo Block * Value Fields in StringFileInfo String Blocks. * Code Page and Language ID Fields of VarFileInfo * Standard Var Blocks. * * By defintion, any value string contained in the String requires * in be localized. It is assumed that there will be two * StringFileInfo Blocks in each international resource. The first * one, is to remain in English, while the second Block, is to be * localized in the language specified by the StingFileInfo Key Field. * The VarFileInfo Code Page and Language ID Fields localized to * indicate which StringFileInfo block the file supports. * * * Arguments: * FILE *InResFile * File to extracte version stamping from * * DWORD *lSize * Size of version stamping information * * VERHEADER *pVerHeader * pointer to structure to contain parsed version info. * * Returns: * * pVerHead Buffer contain version stamping resource * pVerBlock starting location of children blocks * * Errors Codes: * TRUE, Read of Resource sucessfull. * FALSE, Read of Resource failed. * * History: * * 11/91. Created TerryRu. * 10/92. Added Support for NULL Version Blocks TerryRu * 10/92. Added RLRES32 version DaveWi **/
#ifdef RLRES32
WORD GetResVer(
FILE *InResFile, DWORD *plSize, VERHEAD *pVerHead, VERBLOCK **pVerBuf) { WORD wVerHeadSize; WORD wcRead;
*pVerBuf = NULL;
//... Read the fixed info that will not change
wVerHeadSize = (WORD)(3 * sizeof(WORD) + MEMSIZE( lstrlen( TEXT( "VS_VERSION_INFO")) + 1) + sizeof( VS_FIXEDFILEINFO)); wVerHeadSize = DWORDUP(wVerHeadSize);
if ( ResReadBytes( InResFile, (CHAR *)pVerHead, (size_t)wVerHeadSize, plSize) == FALSE ) { return ( (WORD)-1); } //... check for the special case where
//... there is no version block.
if ( wVerHeadSize >= pVerHead->wTotLen) { return ( 0); } //... Version header information read okay
//... so make a buffer for the rest of the res.
*pVerBuf = (VERBLOCK *)FALLOC( DWORDUP( pVerHead->wTotLen) - wVerHeadSize);
//... Now Read Value Information
wcRead = DWORDUP( pVerHead->wTotLen) - wVerHeadSize;
return ( ResReadBytes( InResFile, (CHAR *)*pVerBuf, (size_t)wcRead, plSize) == FALSE ? (WORD)-1 : wcRead); }
#else //... RLRES32
BOOL GetResVer(
FILE *InResFile, DWORD *plSize, VERHEAD *pVerHead, VERBLOCK **pVerBuf) { size_t wcRead = sizeof( VERHEAD);
if ( ResReadBytes( InResFile, (CHAR *) pVerHead, wcRead, plSize) == FALSE ) { return ( FALSE); }
// check for the special case where there is no version block
if ( (size_t)pVerHead->wTotLen == wcRead ) { *pVerBuf = NULL; return ( TRUE); }
// Version header information read okay.
*pVerBuf = (VERBLOCK *)FALLOC( DWORDUP( pVerHead->wTotLen) - wcRead);
// Now Read Value Information
return ( ResReadBytes( InResFile, (CHAR *) *pVerBuf, (size_t)(DWORDUP( pVerHead->wTotLen) - wcRead), plSize)); }
#endif //... RLRES32
/**
* * * Function: GetNameOrd * Function to read either the string name, or ordinal number of a * resource ID. If the ID begins with a 0xff, the resource ID * is a ordinal number, otherwise the ID is a string. * * * Arguments: * InResFile, File handle positioned to location of resource * ID information. * cFlag, pointer to flag indicating which ID type is used. * pwID, pointer of ordinal ID number * pszText pointer, to address of ID string. * * Returns: * cFlag to indicate if ID is string or ordinal number. * pwID, pszText containing actual ID info. * * Errors Codes: * * History: * * 7/91, Implemented TerryRu * 9/91, Inserted cFlag as a indicator for ID or string PeterW * 4/92, Added RLRES32 support TerryRu **/
void GetNameOrd(
FILE *fpInResFile, //... File to retrieve header from
BOOL UNALIGNED*pbFlag,//... For IDFLAG or 1st byte (WORD in RLRES32) of name/ord
WORD UNALIGNED*pwID, //... For retrieved resource ID (if not a string)
TCHAR *UNALIGNED*pszText, // For retrieved resource name if it is a string
DWORD *plSize) // Keeps count of bytes read (or NULL)
{ WORD fFlag;
//... get type info
#ifdef RLRES16
fFlag = GetByte( fpInResFile, plSize);
#else
fFlag = GetWord( fpInResFile, plSize);
#endif
*pbFlag = fFlag;
if ( fFlag == IDFLAG ) { //... field is a numbered item
#ifdef RLRES16
*pwID = GetByte( fpInResFile , plSize); #else
*pwID = GetWord( fpInResFile , plSize); #endif
*pszText = (TCHAR *)FALLOC( 0); } else { static TCHAR szBuf[ 255];
//... field is a named item.
//... put fFlag byte(s) back into stream
//... because it is part of the name.
*pwID = IDFLAG;
#ifdef RLRES16
UnGetByte( fpInResFile, (BYTE) fFlag, plSize); #else
UnGetWord( fpInResFile, (WORD) fFlag, plSize); #endif
GetName( fpInResFile, szBuf, plSize); *pszText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( szBuf) + 1));
lstrcpy( (TCHAR *)*pszText, (TCHAR *)szBuf); } }
/**
* * * Function: GetResHeader * Reads the Resource Header information, and stores it in a structure. * * Arguments: * InResFile, File handle positioned to location of Resource Header. * pResHeader, pointer to Resource Header structure. * * Returns: * pResHeader, containing resource header info. * plSize, contining size of remaining resource info. * * Errors Codes: * -1, Read of resource header failed. * * History: * 7/91, Implemented TerryRu * 4/92, Added RLRES32 Support Terryru * * **/
int GetResHeader(
FILE *InResFile, //... File to get header from
RESHEADER UNALIGNED*pResHeader, //... buffer for the retrieved header
DWORD *plSize) //... keeps track of the bytes read from the file
{
#ifdef RLRES32
pResHeader->lSize = GetdWord( InResFile, plSize); pResHeader->lHeaderSize = GetdWord( InResFile, plSize);
#endif
//... get name ID and type ID
GetNameOrd( InResFile, (BOOL UNALIGNED*)&pResHeader->bTypeFlag, (WORD UNALIGNED*)&pResHeader->wTypeID, (TCHAR *UNALIGNED*)&pResHeader->pszType, plSize);
GetNameOrd( InResFile, (BOOL UNALIGNED*)&pResHeader->bNameFlag, (WORD UNALIGNED*)&pResHeader->wNameID, (TCHAR *UNALIGNED*)&pResHeader->pszName, plSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), plSize);
pResHeader->lDataVersion = GetdWord( InResFile, plSize);
#endif
pResHeader->wMemoryFlags = GetWord( InResFile, plSize);
#ifdef RLRES32
pResHeader->wLanguageId = GetWord( InResFile, plSize); pResHeader->lVersion = GetdWord( InResFile, plSize); pResHeader->lCharacteristics = GetdWord( InResFile, plSize);
#else // RLRES32
pResHeader->lSize = (DWORD)GetdWord( InResFile, plSize);
#endif // RLRES32
return ( 0); }
/**
* * * Function: isdup * Used to determine if the current dialog control id is a duplicate * of an earlyier control id. If so, isdup returns a flag indicating the * ID is a duplicate. * * Arguments: * wcCurrent, ID of current dialog control. * wpIdBuf, array of dialog control ID's processed so far. * wcItems, number of ID's in wpIdBuf * * Returns: * TRUE, ID is a duplicate * FALSE, ID is not a duplicate * * Errors Codes: * None. * * History: * 7/91, Implemented TerryRu * * **/
BOOL isdup(WORD wCurrent, WORD *wpIdBuf, WORD wcItems) { WORD i;
for (i = 0; i < wcItems; i++) { if (wCurrent == wpIdBuf[i]) { return TRUE; } } return FALSE; }
/**
* * * Function: ParseTokCrd * Places dialog coordinates into a buffer. * * Arguments: * pszCrd, buffer to hold dialog control cordinates. * pwX, pwY, pwCX, pwCY, dialog control cordiantes. * * Returns: * NA. * * Errors Codes: * NA. * * History: * 7/91, implemented TerryRu * * **/
void ParseTokCrd( TCHAR *pszCrd, WORD UNALIGNED * pwX, WORD UNALIGNED * pwY, WORD UNALIGNED * pwCX, WORD UNALIGNED * pwCY) { #ifdef RLRES32
int x = 0; int y = 0; int cx = 0; int cy = 0;
_stscanf( pszCrd, TEXT("%d %d %d %d"), &x, &y, &cx, &cy); *pwX = (WORD) x; *pwY = (WORD) y; *pwCX = (WORD) cx; *pwCY = (WORD) cy;
#else //RLRES32
sscanf( pszCrd, "%hd %hd %hd %hd", pwX, pwY, pwCX, pwCY);
#endif //RLRES32
}
int GetAlignFromString( TCHAR *pszStr) { TCHAR *pStyle;
if ( !(pStyle = _tcschr( pszStr, TEXT('('))) ) { return (-1); }
while ( *pStyle ) { if ( *pStyle == TEXT('L') ) { if ( ! _tcsnicmp( pStyle, TEXT("LEFT"), 4) ) { return (0); } } else if ( *pStyle == TEXT('C') ) { if ( ! _tcsnicmp( pStyle, TEXT("CENTER"), 6)) { return (1); } } else if ( *pStyle == TEXT('R') ) { if ( ! _tcsnicmp( pStyle, TEXT("RIGHT"), 5) ) { return (2); } } pStyle++; } return ( -1 ); //none
}
void ParseTokCrdAndAlign( TCHAR *pszCrd, CONTROLDATA *pCntrl) { int align = 0;
if ( (pCntrl->bClass_Flag == IDFLAG) && ((pCntrl->bClass == STATIC) || (pCntrl->bClass == EDIT)) ) {
if ( (align = GetAlignFromString( pszCrd)) >= 0 ) {
if ( pCntrl->bClass == STATIC ) { pCntrl->lStyle &= ~(SS_LEFT|SS_RIGHT|SS_CENTER);
if ( align == 2 ) pCntrl->lStyle |= SS_RIGHT; else if ( align == 1 ) pCntrl->lStyle |= SS_CENTER; else pCntrl->lStyle |= SS_LEFT; } else { pCntrl->lStyle &= ~(ES_LEFT|ES_RIGHT|ES_CENTER);
if ( align == 2 ) pCntrl->lStyle |= ES_RIGHT; else if ( align == 1 ) pCntrl->lStyle |= ES_CENTER; else pCntrl->lStyle |= ES_LEFT; } } } ParseTokCrd( pszCrd, (WORD UNALIGNED *)&pCntrl->x, (WORD UNALIGNED *)&pCntrl->y, (WORD UNALIGNED *)&pCntrl->cx, (WORD UNALIGNED *)&pCntrl->cy); }
/**
* * * Function: PutResHeader * Writes Resource Header information contained in the ResHeader structure * to the ouput resfile. Note, the value of the size field, is not yet * know, so it is left blank, to be fixed up once the size resource * determined. * * Arguments: * OutResFile, File handle to Output Resource File. * ResHeader, Structure containing resource header information. * pResSizePos, file position buffer * * Returns: * pResSizePos, position at localization of the OutResFile to insert * the resource size. * * Errors Codes: * None. * * History: * 7/91, Implemented Terryru * 9/91, Added bTypeFlag to handle case where ID is 255. Peterw * 4/92, Added RLRES32 support Terryru * * **/
int PutResHeader(
FILE *OutResFile, //... File to write to
RESHEADER ResHeader, //... Header to be written out
fpos_t *pResSizePos, //... For offset at which to write the adjusted res size
DWORD *plSize) //... Keeps track of bytes written
{ int rc; DWORD ltSize = *plSize;
#ifdef RLRES32
//... save position to res size
rc = fgetpos( OutResFile, pResSizePos);
//... this size is bogus, will fill in later
//... unless we are called in the mail loop
PutdWord( OutResFile, ResHeader.lSize, plSize); PutdWord( OutResFile, ResHeader.lHeaderSize, plSize);
#endif // RLRES32
PutNameOrd( OutResFile, ResHeader.bTypeFlag, ResHeader.wTypeID, ResHeader.pszType, plSize);
PutNameOrd( OutResFile, ResHeader.bNameFlag, ResHeader.wNameID, ResHeader.pszName, plSize);
#ifdef RLRES32
DWordUpFilePointer( OutResFile, MYWRITE, ftell( OutResFile), plSize);
PutdWord( OutResFile, ResHeader.lDataVersion, plSize);
#endif // RLRES32
PutWord( OutResFile, ResHeader.wMemoryFlags, plSize);
#ifdef RLRES32
PutWord( OutResFile, ResHeader.wLanguageId, plSize); PutdWord( OutResFile, ResHeader.lVersion, plSize); PutdWord( OutResFile, ResHeader.lCharacteristics, plSize);
#else // RLRES32
//... save position to res size
rc = fgetpos( OutResFile, pResSizePos);
//... this size is bogus, will fill in later
//... unless we are called in the mail loop
PutdWord( OutResFile, ltSize, plSize);
#endif // RLRES32
/////////////////// ??????? why? *plSize = ltSize;
return ( rc); }
/**
* * * Function: PutDialog * PutDialog writes dialog information to the output resource file as * it traveres through the linked list of dialog info. If the info * is of the type that needs to be localized, the corresponding translated * info is read from the token file, and writen to the resource file. * * Arguments: * OutResFile, The file handle of the res file being generated. * TokFile, The file handle of the token file containing tokenized dialog info, * typically this file has been localized. * ResHeader, Structure containg Dialog resource header information. * pDialogHdr, Linked list of unlocalized Dialog information. * * Returns: * Translated dialog information written to the Output Resource file. * * Errors Codes: * None, * * History: * 7/91, Implemented. TerryRu * 1/93, Now tokenize dlg fontnames TerryRu * 01/93 Support for var length token text MHotchin * **/
void PutDialog(FILE *OutResFile, FILE *TokFile, RESHEADER ResHeader, DIALOGHEADER *pDialogHdr) { static TOKEN tok; int found = 0; WORD wcDup = 0; WORD *pwIdBuf; static TCHAR pErrBuf[MAXINPUTBUFFER]; WORD i, j = 0, k = 0; fpos_t ResSizePos; CONTROLDATA *pCntlData = pDialogHdr->pCntlData; DWORD lSize = 0; LONG lStartingOffset; // used to dword align file
WORD y = 0; LONG lExtra = 0;
lStartingOffset = ftell(OutResFile);
// Prep for find token call
tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wID = 0; tok.wReserved = ST_TRANSLATED;
lstrcpy( (TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName); tok.szText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( pDialogHdr->pszCaption) + 1)); lstrcpy( (TCHAR *)tok.szText, (TCHAR *)pDialogHdr->pszCaption);
// write the Dialog Res Header
if ( PutResHeader( OutResFile, ResHeader , &ResSizePos, &lSize)) { RLFREE( tok.szText); QuitT( IDS_ENGERR_06, (LPTSTR)IDS_DLGBOX, NULL); } // write the dialog header
lSize = 0L;
#ifdef RLRES32
if (pDialogHdr->fDialogEx) { PutWord( OutResFile, pDialogHdr->wDlgVer, &lSize); PutWord( OutResFile, pDialogHdr->wSignature, &lSize); PutdWord( OutResFile, pDialogHdr->dwHelpID, &lSize); PutdWord( OutResFile, pDialogHdr->lExtendedStyle, &lSize); PutdWord( OutResFile, pDialogHdr->lStyle, &lSize); } else { PutdWord( OutResFile, pDialogHdr->lStyle, &lSize); PutdWord( OutResFile, pDialogHdr->lExtendedStyle, &lSize); }
PutWord( OutResFile, pDialogHdr->wNumberOfItems, &lSize);
#else // RLRES32
PutdWord( OutResFile, pDialogHdr->lStyle, &lSize); PutByte( OutResFile, (BYTE)pDialogHdr->wNumberOfItems, &lSize);
#endif // RLRES32
// check to see if caption was localized
// but don't put it in the res file yet
// order of token is caption, cordinates,
// while in res its cordinates, caption
tok.wFlag = ISCAP;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) { // can not find token, terminate
ParseTokToBuf( pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); }
tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pDialogHdr->pszCaption); pDialogHdr->pszCaption = (TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
TextToBin( pDialogHdr->pszCaption, tok.szText, lstrlen( tok.szText)); RLFREE( tok.szText);
// Now get the cordinates of the token
tok.wFlag = (ISCAP) | (ISCOR);
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) { // token not found, terminate
ParseTokToBuf(pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } tok.wReserved = ST_TRANSLATED;
// token found continue
ParseTokCrd( tok.szText, (WORD UNALIGNED *)&pDialogHdr->x, (WORD UNALIGNED *)&pDialogHdr->y, (WORD UNALIGNED *)&pDialogHdr->cx, (WORD UNALIGNED *)&pDialogHdr->cy);
RLFREE( tok.szText);
// put cordindates in new res file
PutWord(OutResFile, pDialogHdr->x , &lSize); PutWord(OutResFile, pDialogHdr->y , &lSize); PutWord(OutResFile, pDialogHdr->cx , &lSize); PutWord(OutResFile, pDialogHdr->cy , &lSize);
PutNameOrd(OutResFile, pDialogHdr->bMenuFlag, // 9/11/91 (PW)
pDialogHdr->wDlgMenuID, pDialogHdr->pszDlgMenu, &lSize);
PutNameOrd( OutResFile, pDialogHdr->bClassFlag, // 9/11/91 (PW)
pDialogHdr->wDlgClassID, pDialogHdr->pszDlgClass, &lSize);
PutString(OutResFile, pDialogHdr->pszCaption, &lSize);
if ( pDialogHdr->lStyle & DS_SETFONT ) {
if (gfExtendedTok) {
static CHAR szTmpBuf[30];
// find dialog font size
tok.wFlag = ISDLGFONTSIZE; tok.wReserved = ST_TRANSLATED;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) { // token not found, terminate
ParseTokToBuf(pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); }
#ifdef RLRES32
_WCSTOMBS( szTmpBuf, tok.szText, sizeof( szTmpBuf), lstrlen( tok.szText) + 1); PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
if (pDialogHdr->fDialogEx) { PutWord( OutResFile, pDialogHdr->wWeight , &lSize); PutWord( OutResFile, pDialogHdr->wItalic , &lSize); }
#else // RLRES32
PutWord( OutResFile, (WORD) atoi( tok.szText), &lSize);
#endif // RLRES32
RLFREE( tok.szText);
// find dialog font name
tok.wFlag = ISDLGFONTNAME; tok.wReserved = ST_TRANSLATED;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) { // token not found, terminate
ParseTokToBuf(pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } PutString( OutResFile, tok.szText, &lSize); RLFREE( tok.szText);
} else { PutWord( OutResFile, pDialogHdr->wPointSize , &lSize);
if (pDialogHdr->fDialogEx) { PutWord( OutResFile, pDialogHdr->wWeight , &lSize); PutWord( OutResFile, pDialogHdr->wItalic , &lSize); }
PutString( OutResFile, pDialogHdr->pszFontName, &lSize);
}
}
#ifdef RLRES32
DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), &lSize);
#endif // RLRES32
//... That was the end of the DialogBoxHeader
//... Now we start with the ControlData's
pwIdBuf = (WORD *)FALLOC( (DWORD)pDialogHdr->wNumberOfItems * sizeof( WORD));
tok.wReserved = ST_TRANSLATED;
// now place each of the dialog controls in the new res file
for (i = 0; i < pDialogHdr->wNumberOfItems; i ++) { if (isdup ((WORD)pDialogHdr->pCntlData[i].dwID, pwIdBuf, (WORD)j)) { tok.wID = (USHORT)wcDup++; tok.wFlag = ISDUP; } else { // wid is unique so store in buffer for dup check
pwIdBuf[j++] = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wID = (USHORT)pDialogHdr->pCntlData[i].dwID; tok.wFlag = 0; }
if (pDialogHdr->pCntlData[i].pszDlgText[0]) { tok.szText = NULL;
if (!FindToken(TokFile, &tok, ST_TRANSLATED)) { // can not find the token, terminate program
ParseTokToBuf(pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); }
tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pDialogHdr->pCntlData[i].pszDlgText); pDialogHdr->pCntlData[i].pszDlgText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
if ( pDialogHdr->pCntlData[i].pszDlgText ) { TextToBin(pDialogHdr->pCntlData[i].pszDlgText, (TCHAR *)tok.szText, lstrlen((TCHAR *)tok.szText) + 1); } RLFREE( tok.szText); }
tok.wFlag |= ISCOR;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) { ParseTokToBuf( pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } tok.wReserved = ST_TRANSLATED;
ParseTokCrdAndAlign( tok.szText, &pDialogHdr->pCntlData[i] );
RLFREE( tok.szText);
#ifdef RLRES32
if (pDialogHdr->fDialogEx) { PutdWord( OutResFile, pDialogHdr->pCntlData[i].dwHelpID, &lSize); PutdWord( OutResFile, pDialogHdr->pCntlData[i].lExtendedStyle, &lSize); PutdWord( OutResFile, pDialogHdr->pCntlData[i].lStyle, &lSize); } else { PutdWord( OutResFile, pDialogHdr->pCntlData[i].lStyle, &lSize); PutdWord( OutResFile, pDialogHdr->pCntlData[i].lExtendedStyle, &lSize); }
#endif // RLRES32
// now put control info into res file
PutWord (OutResFile, pDialogHdr->pCntlData[i].x , &lSize); PutWord (OutResFile, pDialogHdr->pCntlData[i].y , &lSize); PutWord (OutResFile, pDialogHdr->pCntlData[i].cx , &lSize); PutWord (OutResFile, pDialogHdr->pCntlData[i].cy , &lSize);
if (pDialogHdr->fDialogEx) PutdWord (OutResFile, pDialogHdr->pCntlData[i].dwID , &lSize); else PutWord (OutResFile, (WORD)pDialogHdr->pCntlData[i].dwID , &lSize);
#ifdef RLRES16
// lStyle
PutdWord (OutResFile, pDialogHdr->pCntlData[i].lStyle , &lSize);
PutByte(OutResFile, (BYTE) pDialogHdr->pCntlData[i].bClass, &lSize);
if (! (pDialogHdr->pCntlData[i].bClass & 0x80)) { PutString (OutResFile, pDialogHdr->pCntlData[i].pszClass , &lSize); }
#else // RLRES16
PutNameOrd(OutResFile, pDialogHdr->pCntlData[i].bClass_Flag, // 9/11/91 (PW)
pDialogHdr->pCntlData[i].bClass, pDialogHdr->pCntlData[i].pszClass, &lSize);
#endif // RLRES16
PutNameOrd(OutResFile, pDialogHdr->pCntlData[i].bID_Flag, // 9/11/91 (PW)
pDialogHdr->pCntlData[i].wDlgTextID, pDialogHdr->pCntlData[i].pszDlgText, &lSize);
#ifdef RLRES16
PutByte(OutResFile, (BYTE) pDialogHdr->pCntlData[i].unDefined, &lSize); #else
PutWord(OutResFile, (WORD)pDialogHdr->pCntlData[i].wExtraStuff, &lSize);
if (pDialogHdr->fDialogEx && pDialogHdr->pCntlData[i].wExtraStuff) { lExtra = pDialogHdr->pCntlData[i].wExtraStuff; y = 0; while ( lExtra-- ) PutByte (OutResFile, pDialogHdr->pCntlData[i].pExtraStuff[y++] , &lSize); }
if ( i < pDialogHdr->wNumberOfItems - 1 ) { DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), &lSize); }
#endif // RLRES16
}
RLFREE( pwIdBuf );
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) { QuitT( IDS_ENGERR_07, (LPTSTR)IDS_DLGBOX, NULL); } DWordUpFilePointer( OutResFile, MYWRITE, ftell( OutResFile), NULL); }
/**
* * * Function: PutMenu * Traveres through the linked list of Menu information and writes the info to the * output resource file. If the infortion is the type that requires localization, * the translated info is read from the token file and writen to the resource. * call PutMenuItem to do the actual write of the menu info to the resource. * * Arguments: * OutResFile, File handle of output resource file. * TokFile, File handle of token file. * ResHeader, Sturcture contain Menu Resource header information. * pMenuHdr, Linked list of menu info. * * Returns: * Translated Menu Info written to output resource file. * * Errors Codes: * None. * * History: * 7/91, Implemented. TerryRu. * 01/93 Changes to allow var length token text. MHotchin * **/
void PutMenu(FILE *OutResFile, FILE *TokFile, RESHEADER ResHeader, MENUHEADER *pMenuHdr) { DWORD lSize = 0; static TOKEN tok; static WORD wcPopUp = 0; fpos_t ResSizePos; MENUITEM *pMenuItem = pMenuHdr->pMenuItem; static TCHAR pErrBuf[ MAXINPUTBUFFER]; LONG lExtra = 0; WORD i = 0;
// write the Menu Res header
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) { QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MENU, NULL); }
lSize = 0;
// write the Menu header
PutWord (OutResFile, pMenuHdr->wVersion, &lSize); PutWord (OutResFile, pMenuHdr->cbHeaderSize , &lSize);
if (pMenuHdr->fMenuEx && pMenuHdr->cbHeaderSize) { lExtra = pMenuHdr->cbHeaderSize; while ( lExtra-- ) PutByte (OutResFile, pMenuHdr->pExtraStuff[i++] , &lSize); }
// prep for findtoken call
tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wReserved = ST_TRANSLATED;
// for all menu items,
// find translated token if item was tokenized
// write out that menu item, using new translation if available.
while (pMenuItem) { // if Menu Item is a seperator skip it
if ( *pMenuItem->szItemText ) { // check for the popup menu items
if ((pMenuItem->fItemFlags & MFR_POPUP) && pMenuHdr->fMenuEx) { tok.wID = (pMenuItem->dwMenuID == 0 || pMenuItem->dwMenuID == 0x0000ffff) ? (USHORT)pMenuItem->dwMenuID : 0x8000 + wcPopUp++; tok.wFlag = ISPOPUP; } else if (pMenuItem->fItemFlags & POPUP) { tok.wID = wcPopUp++; tok.wFlag = ISPOPUP; } else { tok.wID = (USHORT)pMenuItem->dwMenuID; tok.wFlag = 0; } lstrcpy((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName); tok.szText = NULL;
if ( ! FindToken( TokFile, &tok,ST_TRANSLATED) ) { // can not find token, terminate
ParseTokToBuf(pErrBuf, &tok); RLFREE( tok.szText); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pMenuItem->szItemText); pMenuItem->szItemText= (TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
TextToBin(pMenuItem->szItemText, (TCHAR *)tok.szText, lstrlen((TCHAR *)tok.szText)+1); RLFREE( tok.szText); }
PutMenuItem (OutResFile, pMenuItem , &lSize, pMenuHdr->fMenuEx);
pMenuItem = pMenuItem->pNextItem; }
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) { QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MENU, NULL); } }
/**
* * * Function: PutMenuItem * Called by PutMenu to write a menu item info to the ouput resoruce file. * * * Arguments: * OutResFile, File handle of output resfile, positioned at location to * write menu item info. * pMenuItem, pointer to struture containing menu item info. * plSize, pointer of variable to count the number of bytes written to * the resource file. Used later to fixup the resource field in the * header. * * * * Returns: * OutReFile, containing translated menu item info, and plSize containing * number of bytes written to resource file. * * Errors Codes: * None. * * History: * 7//91, Implemented TerryRu
* * **/
void PutMenuItem(FILE * OutResFile, MENUITEM * pMenuItem, DWORD * plSize, BOOL fMenuEx) { if (fMenuEx) { PutdWord( OutResFile, pMenuItem->dwType, plSize); PutdWord( OutResFile, pMenuItem->dwState, plSize); PutdWord( OutResFile, pMenuItem->dwMenuID, plSize); PutWord( OutResFile, pMenuItem->fItemFlags, plSize); } else { PutWord( OutResFile, pMenuItem->fItemFlags, plSize);
if ( ! (pMenuItem->fItemFlags & POPUP) ) { PutWord( OutResFile, (WORD)pMenuItem->dwMenuID, plSize); } }
PutString( OutResFile, pMenuItem->szItemText, plSize);
if (fMenuEx) { DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), plSize);
if (pMenuItem->fItemFlags & MFR_POPUP) { PutdWord( OutResFile, pMenuItem->dwHelpID, plSize); } }
}
/**
* * * Function: PutNameOrd * Writes either the string or ordinal ID of the resource class or type. * * * Arguments: * OutResFile, File handle of resource file being generated. * bFlag, Flag indicating whether ID is a string or ordinal. * pszText, string ID, if used. * wId, Ordinal ID if used. * pLsize, pointer to DWORD counter var. * * Returns: * OutResFile, containing ID info, and plSize containing the number of * bytes written to the file. * * Errors Codes: * None. * * History: * 7/91, Implemented. TerryRu. * * **/
void PutNameOrd(
FILE *fpOutResFile, BOOL bFlag, WORD wID, TCHAR *pszText, DWORD *plSize) { if ( bFlag == IDFLAG ) {
#ifdef RLRES16
PutByte( fpOutResFile, (BYTE)IDFLAG, plSize);
#else
PutWord( fpOutResFile, (WORD)IDFLAG, plSize);
#endif
PutWord( fpOutResFile, wID, plSize); } else { PutString( fpOutResFile, pszText, plSize); } }
/**
* * * Function: MyAtow, * Special Ascii to WORD function that works on 4 digit, hex strings. * * * Arguments: * pszNum, 4 digit hex string to convert to binary. * * * Returns: * Binary value of pszNumString * * Errors Codes: * None. * * History: * 12//91, Implemented. TerryRu.
* * **/
WORD MyAtoX(
CHAR *pszNum, //... array of bytes to scan
int nLen) //... # oc bytes in pszNum to scan
{ WORD wNum = 0; WORD i; WORD nPower = 1;
if ( nLen > 4 ) { QuitT( IDS_ENGERR_16, (LPTSTR)IDS_CHARSTOX, NULL); }
for ( i = 0; i < nLen; i++, nPower *= 16 ) { if ( isdigit( pszNum[ i]) ) { wNum += nPower * (pszNum[i] - '0'); } else { wNum += nPower * (toupper( pszNum[i]) - 'A' + 10); } } return ( wNum); }
WORD MyAtoW( CHAR *pszNum) { return ( MyAtoX( pszNum, 4)); }
/**
* * * Function: PutResVer. * Writes the Version stamping info to the Resourc file. Unlike most * put functions, PutResVer writes all the localized version stamping info * into a memory block, then writes the complete version stamping info to * the resource file. This was done because of large number of size * fixups needed for the version stamping info. * * * Arguments: * OutResFile, file pointer of resource file being generated. * TokeFile, file pointer of input token file containing localized info. * ResHeader, Structure containing Resource Header info of the * version stamping block. * pVerHdr, address of Version Header. Note this is different the ResHdr. * pVerBlk, address of Version stamping info, which is contained in * a series of StringFile, and VarFile info blocks. The number of * such blocks is determined by the size fields. * * Returns: * OutResFile, containing localized version stamping info. * * Errors Codes: * None. * * History: * 11/91, Implemented. TerryRu. * 12/91, Various fixes to work with different padding. TerryRu. * 01/92, Size of Version block updated PeterW. * 10/92, Now handles NULL Version Blocks TerryRu. * 10/92, Added RLRES32 version DaveWi * 01/93, Added var length token text support. MHotchin **/
#ifdef RLRES32
int PutResVer(
FILE *fpOutResFile, FILE *fpTokFile, RESHEADER ResHeader, VERHEAD *pVerHdr, VERBLOCK *pVerBlk) { TOKEN Tok; BOOL fInStringInfo = FALSE; //... TRUE if reading StringFileInfo
WORD wTokNum = 0; //... Put into Tok.wID field
WORD wTokContinueNum = 0; //... Put into Tok.wFlag field
WORD wDataLen = 0; //... Length of old resource data
WORD wVerHeadSize; //... Sizeof of the VERHEAD struct
fpos_t lResSizePos; DWORD lSize = 0L; int nWritten = 0; int nNewVerBlockSize = 0; PVERBLOCK pNewVerStamp = NULL; PVERBLOCK pNewBlk = NULL;
wVerHeadSize = (WORD)(3 * sizeof(WORD) + MEMSIZE( lstrlen( TEXT( "VS_FIXEDFILEINFO")) + 1) + sizeof( VS_FIXEDFILEINFO)); wVerHeadSize = DWORDUP(wVerHeadSize);
//... write the Version resouce header
if ( PutResHeader(fpOutResFile, ResHeader, &lResSizePos, &lSize) ) { QuitT( IDS_ENGERR_06, (LPTSTR)IDS_VERSTAMP, NULL); }
lSize = 0L;
if ( pVerBlk == NULL ) { //... We have no version block to write
//... just write the version header and return
nWritten = fwrite((void *)pVerHdr, sizeof(char), wVerHeadSize, fpOutResFile);
if (! UpdateResSize(fpOutResFile, &lResSizePos, (DWORD)nWritten)) { QuitT( IDS_ENGERR_07, (LPTSTR)IDS_VERSTAMP, NULL); } return (1); }
wDataLen = pVerHdr->wTotLen;
if ( wDataLen == 0 || wDataLen == (WORD)-1 ) { return (-1); //... No resource data
} //... Allocate buffer to hold New Version
//... Stamping Block (make ne buffer large to
//... account for expansion of strings during
//... localization).
pNewVerStamp = (PVERBLOCK)FALLOC( (nNewVerBlockSize = wDataLen * 4));
//... Fill new memory block with zeros
memset((void *)pNewVerStamp, 0, nNewVerBlockSize);
//... Copy version header into buffer
memcpy((void *)pNewVerStamp, (void *)pVerHdr, wVerHeadSize); pNewVerStamp->wLength = wVerHeadSize;
//... Move to start of new version info block
pNewBlk = (PVERBLOCK)((PBYTE)pNewVerStamp + wVerHeadSize);
wDataLen -= wVerHeadSize;
//... Fill in static part of TOKEN struct
Tok.wType = ResHeader.wTypeID; Tok.wName = IDFLAG; Tok.szName[0] = TEXT('\0'); Tok.szType[0] = TEXT('\0'); Tok.wReserved = ST_TRANSLATED;
//... Get a token for each string found in res
while (wDataLen > 0) { WORD wRC;
//... Start of a StringFileInfo block?
#ifdef UNICODE
wRC = (WORD)CompareStringW( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, pVerBlk->szKey, min( wDataLen, (WORD)STRINGFILEINFOLEN), STRINGFILEINFO, min( wDataLen, (WORD)STRINGFILEINFOLEN)); if ( wRC == 2 ) #else
wRC = strncmp( pVerBlk->szKey, STRINGFILEINFO, min( wDataLen, (WORD)STRINGFILEINFOLEN));
if ( wRC == SAME ) #endif
{ WORD wStringInfoLen = 0; //... # of bytes in StringFileInfo
WORD wLen = 0; PVERBLOCK pNewStringInfoBlk; //... Start of this StringFileInfo blk
pNewStringInfoBlk = pNewBlk;
pNewStringInfoBlk->wLength = 0; //... Gets fixed up later
pNewStringInfoBlk->wValueLength = 0; pNewStringInfoBlk->wType = pVerBlk->wType;
lstrcpy( (TCHAR *)pNewStringInfoBlk->szKey, (TCHAR *)pVerBlk->szKey);
//... Get # of bytes in this StringFileInfo
//... (Length of value is always 0 here)
wStringInfoLen = pVerBlk->wLength;
//... Move to start of first StringTable blk.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK) - sizeof(TCHAR) + MEMSIZE( STRINGFILEINFOLEN)));
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen); pNewBlk = (PVERBLOCK)((PBYTE)pNewStringInfoBlk + wLen);
DECWORDBY(&wDataLen, wLen); DECWORDBY(&wStringInfoLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen); INCWORDBY(&pNewStringInfoBlk->wLength, wLen);
while (wStringInfoLen > 0) { WORD wStringTableLen = 0; PVERBLOCK pNewStringTblBlk = NULL;
//... Get # of bytes in this StringTable
//... (Length of value is always 0 here)
wStringTableLen = pVerBlk->wLength;
//... Copy StringFileInfo key into Token name
Tok.wID = wTokNum++; Tok.wFlag = wTokContinueNum = 0; lstrcpy((TCHAR *)Tok.szName, (TCHAR *)LANGUAGEINFO); Tok.szText = NULL;
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) { //... token not found, flag error and exit.
ParseTokToBuf( (TCHAR *)szDHW, &Tok); RLFREE( pNewVerStamp); RLFREE( Tok.szText); QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL); } Tok.wReserved = ST_TRANSLATED;
//... Copy lang string into buffer
pNewStringTblBlk = pNewBlk;
pNewStringTblBlk->wLength = 0; //... fixed up later
pNewStringTblBlk->wValueLength = 0; pNewStringTblBlk->wType = pVerBlk->wType;
CopyMemory( pNewStringTblBlk->szKey, Tok.szText, MEMSIZE( LANGSTRINGLEN));
RLFREE( Tok.szText);
//... Move to start of first String.
wLen = DWORDUP( sizeof(VERBLOCK) - sizeof(TCHAR) + MEMSIZE( LANGSTRINGLEN));
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen); pNewBlk = (PVERBLOCK)((PBYTE)pNewBlk + wLen);
DECWORDBY(&wDataLen, wLen); DECWORDBY(&wStringInfoLen, wLen); DECWORDBY(&wStringTableLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen); INCWORDBY(&pNewStringInfoBlk->wLength, wLen); INCWORDBY(&pNewStringTblBlk->wLength, wLen);
while ( wStringTableLen > 0 ) { //... Is value a string?
if (pVerBlk->wType == VERTYPESTRING) { wTokContinueNum = 0;
Tok.wID = wTokNum++; Tok.wReserved = ST_TRANSLATED;
lstrcpy( (TCHAR *)pNewBlk->szKey, (TCHAR *)pVerBlk->szKey);
pNewBlk->wLength = DWORDUP(sizeof(VERBLOCK) + MEMSIZE(lstrlen((TCHAR *)pNewBlk->szKey)));
Tok.wFlag = wTokContinueNum++;
lstrcpy( (TCHAR *)Tok.szName, (TCHAR *)pVerBlk->szKey);
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) { //... token not found, flag error and exit.
ParseTokToBuf( (TCHAR *)szDHW, &Tok); RLFREE( pNewVerStamp); QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL); }
Tok.wReserved = ST_TRANSLATED;
pNewBlk->wValueLength = (WORD)TextToBinW( (TCHAR *)((PCHAR)pNewBlk + pNewBlk->wLength), Tok.szText, 2048);
pNewBlk->wType = VERTYPESTRING; pNewBlk->wLength += MEMSIZE( pNewBlk->wValueLength);
INCWORDBY(&pNewVerStamp->wLength, DWORDUP(pNewBlk->wLength)); INCWORDBY(&pNewStringInfoBlk->wLength, DWORDUP(pNewBlk->wLength)); INCWORDBY(&pNewStringTblBlk->wLength, DWORDUP(pNewBlk->wLength));
pNewBlk = MoveAlongVer(pNewBlk, NULL, NULL, NULL);
RLFREE( Tok.szText); } //... Move to start of next String.
pVerBlk = MoveAlongVer(pVerBlk, &wDataLen, &wStringInfoLen, &wStringTableLen);
} //... END while wStringTableLen
} //... END while wStringInfoLen
} else { if (_tcsncmp((TCHAR *)pVerBlk->szKey, (TCHAR *)VARFILEINFO, min(wDataLen, (WORD)VARFILEINFOLEN)) == SAME) { WORD wVarInfoLen = 0; //... # of bytes in VarFileInfo
WORD wNewVarInfoLen = 0; //... # of bytes in new VarFileInfo
WORD wLen = 0; PVERBLOCK pNewVarStart = NULL; //... Start of VarInfo block
wVarInfoLen = pVerBlk->wLength; pNewVarStart = pNewBlk;
//... Get # of bytes in this VarFileInfo
//... (Length of value is always 0 here)
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK) - sizeof(TCHAR) + MEMSIZE( VARFILEINFOLEN)));
//... Copy non-localized header
//... pNewVarStart->wLength field fixed up later
memcpy((void *)pNewVarStart, (void *)pVerBlk, wLen); pNewVarStart->wLength = wLen;
//... Move to start of first Var.
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen); pNewBlk = (PVERBLOCK)((PBYTE)pNewBlk + wLen);
DECWORDBY(&wDataLen, wLen); DECWORDBY(&wVarInfoLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen);
while (wDataLen > 0 && wVarInfoLen > 0) { if (_tcsncmp((TCHAR *)pVerBlk->szKey, (TCHAR *)TRANSLATION, min(wDataLen, (WORD)TRANSLATIONLEN)) == SAME) { WORD wTransLen = 0; PBYTE pValue = NULL;
wTokContinueNum = 0;
//... Copy VarFileInfo key into Token
Tok.wID = wTokNum; Tok.wFlag = wTokContinueNum++; Tok.szText = NULL; lstrcpy((TCHAR *)Tok.szName, (TCHAR *)TRANSLATION);
Tok.wReserved = ST_TRANSLATED;
pNewBlk->wLength = DWORDUP(sizeof(VERBLOCK) + MEMSIZE(lstrlen((TCHAR *)TRANSLATION)));
INCWORDBY(&pNewVerStamp->wLength, pNewBlk->wLength); INCWORDBY(&pNewVarStart->wLength, pNewBlk->wLength);
pNewBlk->wValueLength = 0; //... fixed up later
pNewBlk->wType = VERTYPEBINARY; lstrcpy( (TCHAR *)pNewBlk->szKey, (TCHAR *)TRANSLATION); lstrcpy((TCHAR *)Tok.szName, (TCHAR *)TRANSLATION);
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) { //... token not found, flag error and exit.
ParseTokToBuf((TCHAR *)szDHW, &Tok); RLFREE( pNewVerStamp); RLFREE( Tok.szText); QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL); } else { PCHAR pszLangIDs = NULL; PCHAR pszLangStart = NULL; WORD wLangIDCount = 0; size_t nChars;
//... Get # chars in input string (token text)
wTransLen = (WORD)lstrlen( Tok.szText);
pszLangIDs = (PCHAR)FALLOC( MEMSIZE( wTransLen + 1));
nChars = _WCSTOMBS( pszLangIDs, Tok.szText, MEMSIZE( wTransLen + 1), wTransLen + 1);
RLFREE( Tok.szText);
if ( ! nChars ) { RLFREE( pNewVerStamp); RLFREE( pszLangIDs); QuitT( IDS_ENGERR_14, (LPTSTR)IDS_INVVERCHAR, NULL); }
//... Where to put these bytes?
pValue = (PBYTE)GetVerValue( pNewBlk);
//... Get each lang ID in the token
for ( wLangIDCount = 0, pszLangStart = pszLangIDs; wTransLen >= 2 * TRANSDATALEN; ++wLangIDCount ) { USHORT uByte1 = 0; USHORT uByte2 = 0; WORD wIndex = 0;
if ( sscanf( pszLangStart, "%2hx%2hx", &uByte2, &uByte1) != 2 ) { QuitA( IDS_ENGERR_16, (LPSTR)IDS_ENGERR_21, pszLangStart); }
wIndex = wLangIDCount * TRANSDATALEN;
pValue[ wIndex] = (BYTE)uByte1; pValue[ wIndex + 1] = (BYTE)uByte2;
INCWORDBY(&pNewVerStamp->wLength, TRANSDATALEN); INCWORDBY(&pNewVarStart->wLength, TRANSDATALEN); INCWORDBY(&pNewBlk->wLength, TRANSDATALEN); INCWORDBY(&pNewBlk->wValueLength, TRANSDATALEN);
//... Set up to get next lang ID in token
wTransLen -= 2 * TRANSDATALEN; pszLangStart += 2 * TRANSDATALEN;
while ( wTransLen > 2 * TRANSDATALEN && *pszLangStart != '\0' && isspace( *pszLangStart) ) { wTransLen--; pszLangStart++; } } //... END for ( wLangIDCount = 0 ...
RLFREE( pszLangIDs); } Tok.wReserved = ST_TRANSLATED;
} //... END if (_tcsncmp((TCHAR *)pVerBlk->szKey))
//... Move to start of next Var info block.
pVerBlk = MoveAlongVer(pVerBlk, &wDataLen, &wVarInfoLen, NULL);
pNewBlk = MoveAlongVer(pNewBlk, NULL, NULL, NULL);
} //... END while (wDataLen > 0 && wVarInfoLen)
} else { RLFREE( pNewVerStamp); QuitT( IDS_ENGERR_14, (LPTSTR)IDS_INVVERBLK, NULL); } } } //... END while (wDataLen)
//... write new version stamping information
//... to the resource file
nWritten = fwrite((void *)pNewVerStamp, sizeof(char), (WORD)lSize + pNewVerStamp->wLength, fpOutResFile);
if ( ! UpdateResSize( fpOutResFile, &lResSizePos, lSize + pNewVerStamp->wLength) ) { RLFREE( pNewVerStamp);
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_VERSTAMP, NULL); } RLFREE( pNewVerStamp);
return (0); }
#else //... #ifdef RLRES32
int PutResVer(
FILE *OutResFile, FILE *TokFile, RESHEADER ResHeader, VERHEAD *pVerHdr, VERBLOCK *pVerBlk) {
TCHAR *pszBuf; fpos_t ResSizePos; WORD wcLang = 0, wcBlock = 0; TOKEN tok; VERBLOCK *pCurBlk; VERBLOCK *pNewBlk, *pNewBlkStart; TCHAR *pszStr, pErrBuf[ 128]; WORD *pwVal; DWORD lTotBlkSize, lSize = 0; int wTotLen, wcCurBlkLen, wcTransBlkLen, wcRead; WORD *pStrBlkSizeLoc, wStrBlkSize = 0; int wcBlkLen;
// write the Version resouce header
if ( PutResHeader( OutResFile, ResHeader, &ResSizePos, &lSize) ) { QuitT( IDS_ENGERR_06, MAKEINTRESOURCE( IDS_VERSTAMP), NULL); }
lSize = 0L;
if ( pVerBlk == NULL ) { //... We have no version block to write
//... just write the version header and return
wcRead = fwrite( (void *)pVerHdr, sizeof( char), sizeof( VERHEAD), OutResFile);
if ( ! UpdateResSize( OutResFile, &ResSizePos, (DWORD)wcRead) ) { QuitT( IDS_ENGERR_07, MAKEINTRESOURCE( IDS_VERSTAMP), NULL); } return ( 1); }
wTotLen = pVerBlk->nTotLen;
// Allocate buffer to hold New Version Stamping Block
pNewBlk = (VERBLOCK *)FALLOC( VERMEM));
// Set new memory block to NULLS
memset( (void *)pNewBlk, 0, VERMEM);
// save start of new version info block
pNewBlkStart = pNewBlk; wcTransBlkLen = sizeof(VERHEAD); lSize += wcTransBlkLen;
// Insert version header info into new version info bluffer
memcpy((void *)pNewBlk, (void *)pVerHdr, wcTransBlkLen);
// Position pNewBlk point at location to insert next piece of version info
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcTransBlkLen);
// File in static part of TOKEN struct
tok.wType = ResHeader.wTypeID; tok.wName = IDFLAG; tok.wReserved = ST_TRANSLATED;
wTotLen = pVerBlk->nTotLen; pCurBlk = pVerBlk;
tok.wID = wcLang++; pszStr = pCurBlk->szKey;
wcCurBlkLen = 4 + DWORDUP(lstrlen((TCHAR *)pszStr) + 1); wTotLen -= wcCurBlkLen;
// Insert StringFileInfo Header into new version info buffer
// this info is not localized
memcpy((void *)pNewBlk, (void *)pCurBlk, wcCurBlkLen); pszStr=pNewBlk->szKey;
// reposition pointers
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + wcCurBlkLen); pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcCurBlkLen);
lSize += wcCurBlkLen;
// Read All the StringTableBlocks
while (wTotLen > 8) {
// For String tables blocks we localizes the key field
tok.wFlag = ISKEY;
wcBlkLen = pCurBlk->nTotLen;
lstrcpy((TCHAR *)tok.szName, TEXT("Language Info")); tok.wID = wcBlock; tok.szText = NULL;
if ((pszStr = FindTokenText (TokFile,&tok,ST_TRANSLATED)) == NULL) { // token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok); QuitT( IDS_ENGERR_05, pErrBuf, NULL); }
RLFREE(tok.szText); tok.szText = NULL;
tok.wReserved = ST_TRANSLATED; // Do not know length of the translated StringTable block
// so set the nValLen to zero , and save location
// of string file block size field, to be fixed up latter.
pNewBlk->nValLen = 0; pStrBlkSizeLoc = (WORD *) &pNewBlk->nTotLen;
// copy the translated key into that location
TextToBin(pNewBlk->szKey,pszStr,VERMEM-2*sizeof(int)); RLFREE( pszStr);
// Update localized string block count
wStrBlkSize = (WORD) DWORDUP (4 + lstrlen((TCHAR *)pNewBlk->szKey) + 1);
// get the length of the current block, note the
// translated length does not change.
wcCurBlkLen = 4 + pVerBlk->nValLen + DWORDUP(lstrlen((TCHAR *)pCurBlk->szKey) + 1); lSize += wStrBlkSize;
// Update counter vars
wTotLen -= DWORDUP(wcBlkLen); wcBlkLen -= wcCurBlkLen;
// repostion pointers
pCurBlk = (VERBLOCK *) ((char *)pCurBlk + DWORDUP(wcCurBlkLen)); pNewBlk = (VERBLOCK *) ((char *)pNewBlk + DWORDUP(wcCurBlkLen)) ;
// Read the String Blocks
// For String Blocks we localize the value fields.
tok.wFlag = ISVAL;
while (wcBlkLen > 0) { // for string blocks we translate the value fields.
pszStr = pCurBlk->szKey; lstrcpy((TCHAR *)tok.szName, (TCHAR *)pszStr); tok.szText = NULL;
if ((pszStr= FindTokenText(TokFile,&tok,ST_TRANSLATED)) == NULL) { //token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } RLFREE(tok.szText); tok.szText = NULL;
tok.wReserved = ST_TRANSLATED;
lstrcpy((TCHAR *)pNewBlk->szKey, (TCHAR *)pCurBlk->szKey);
// position pointer to location to insert translated token text into pCurBlk
pszBuf = (TCHAR*) pNewBlk + 4 + DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey) + 1);
// now insert the token text
TextToBin(pszBuf, pszStr , VERMEM - (4+DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey)+1))); RLFREE( pszStr);
// fix up counter fields in pNewBlk
pNewBlk->nValLen = lstrlen((TCHAR *)pszBuf) + 1; pNewBlk->nTotLen = 4 + pNewBlk->nValLen + DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey) + 1);
wcBlkLen -= DWORDUP(pCurBlk->nTotLen);
lSize += DWORDUP(pNewBlk->nTotLen); wStrBlkSize += DWORDUP(pNewBlk->nTotLen);
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + DWORDUP(pCurBlk->nTotLen)); pNewBlk = (VERBLOCK *) ((char *) pNewBlk + DWORDUP(pNewBlk->nTotLen)); } // while
wcBlock ++; *pStrBlkSizeLoc = wStrBlkSize ; }
// this stuff is not translated so just copy it straight over
// Skip past Head of VarInfoBlock
pszStr = pCurBlk->szKey; wTotLen = pCurBlk->nTotLen; wcCurBlkLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= wcCurBlkLen;
// Insert Head of Var Info Into new block buffer
memcpy((void *)pNewBlk, (void *)pCurBlk, wcCurBlkLen);
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + wcCurBlkLen); pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcCurBlkLen);
lTotBlkSize = lSize; // Save the size value for the total Version blk (PW)
lSize += wcCurBlkLen;
wcLang = 0;
// Read the Var Info Blocks
// For Var Info Blocks we localize the Translation Value field.
tok.wFlag = ISVAL;
while (wTotLen > 0) { pszStr = pCurBlk->szKey; lstrcpy((TCHAR *)tok.szName, TEXT("Translation")); tok.wID = wcLang; tok.szText = NULL;
// Read Language ID
if ((pszStr = FindTokenText(TokFile, &tok,ST_TRANSLATED)) == NULL) { //token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } RLFREE(tok.szText); tok.szText = NULL;
tok.wReserved = ST_TRANSLATED;
// Found ascii translation string,
// convert it to binary and insert into pCurBlk
pwVal = (WORD *)((char *)pCurBlk + DWORDUP(4 + lstrlen((TCHAR *)pCurBlk->szKey) + 1));
*pwVal = MyAtoW((CHAR *)pszStr); pwVal++; *pwVal = MyAtoW((CHAR *)&pszStr[4]);
wcLang ++; wTotLen -= DWORDUP(pCurBlk->nTotLen ); memcpy((void *)pNewBlk, (void *)pCurBlk, pCurBlk->nTotLen);
lSize += pCurBlk->nTotLen;
// reposition pointers
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + DWORDUP(pCurBlk->nTotLen) + 4); pNewBlk = (VERBLOCK *) ((char *) pNewBlk + DWORDUP(pNewBlk->nTotLen) + 4); RLFREE( pszStr);
} // Now fixup VerHeader Size. header not localized so
// we do not need to update the value size.
pVerHdr = (VERHEAD *) pNewBlkStart; pVerHdr->wTotLen = (WORD) lSize;
// Update first size value of Version block (PW)
wcTransBlkLen = sizeof (VERHEAD); pNewBlk = (VERBLOCK *) ((char *) pNewBlkStart + wcTransBlkLen); pNewBlk->nTotLen = (WORD) (lTotBlkSize - wcTransBlkLen);
// write new version stamping information to the resource file
wcRead = fwrite( (void *)pNewBlkStart, sizeof(char), (size_t)lSize, OutResFile);
if (!UpdateResSize (OutResFile, &ResSizePos, lSize)) { QuitT( IDS_ENGERR_07, MAKEINTRESOURCE( IDS_VERSTAMP), NULL); } RLFREE( pNewBlkStart); }
#endif //... RLRES32
/**
* * * Function: PutStrHdr. * Writes the string block info to the resource file. * * * Arguments: * OutResFile, pointer to resource file being generated. * TokFile, pointer to token file containing localized string blocks. * ResHeader, structure containing Resource Header info for the string block. * pStrHder, Array of strings defined in the string block. * * * Returns: * OutResFile, containing localized string blocks. * * Errors Codes: * None. * * * History: * 7/91. Implemented. TerryRu. * 01/93 Added support for var length token text strings. MHotchin * **/
void PutStrHdr( FILE * OutResFile, FILE * TokFile, RESHEADER ResHeader, STRINGHEADER *pStrHdr) { static TOKEN tok; WORD i, j, k; static TCHAR pErrBuf[MAXINPUTBUFFER]; fpos_t ResSizePos; DWORD lSize = 0;
// write the Menu Res header
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) { QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MENU, NULL); }
lSize = 0L;
for (i = 0; i < 16; i++) { tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wID = i; tok.wFlag = 0; tok.wReserved = ST_TRANSLATED; tok.szText = NULL; tok.szName[0] = 0;
lstrcpy((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
if ( ! FindToken(TokFile, &tok, ST_TRANSLATED) ) { // can not find token, terminate
ParseTokToBuf( pErrBuf, &tok); QuitT( IDS_ENGERR_05, pErrBuf, NULL); } tok.wReserved = ST_TRANSLATED;
// token text found continue
{ static TCHAR szTmp[4160]; int cChars = 0; //... # chars in token text, including nul
cChars = lstrlen( tok.szText) + 1;
j = TextToBin( szTmp, tok.szText, cChars) - 1; RLFREE( tok.szText);
#ifdef RLRES16
PutByte( OutResFile, (BYTE) j, &lSize); #else
PutWord( OutResFile, j, &lSize); #endif
for (k = 0; k < j; k++) { #ifdef RLRES16
PutByte( OutResFile, szTmp[k], &lSize); #else
PutWord( OutResFile, szTmp[k], &lSize); #endif
} } }
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) { QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MENU, NULL); } }
/**
* * * Function: GetString. * Read a block of 16 strings from string block in the resource file. * * Arguments: * InResFile, file pointer to location of string block in the * resource file. * lSize, dummy var not used. * * Returns: * pStrHdr containing 16 strings. * * * Errors Codes: * None. * * History: * 7/91. Implemented. TerryRu. * * **/ STRINGHEADER *GetString( FILE *InResFile, DWORD *lSize) {
WORD wCharsLeft = 0; // Count of remaining characters in the string
WORD i = 0, j = 0; // Indexes into current block of 16 strings
STRINGHEADER *pStrHdr;
pStrHdr = (STRINGHEADER *)FALLOC( sizeof( STRINGHEADER));
for (j = 0; j < 16; j ++) { #ifdef RLRES16
wCharsLeft = pStrHdr->sChars[j] = (WORD)GetByte( InResFile, lSize); #else
wCharsLeft = pStrHdr->wChars[j] = GetWord( InResFile, lSize); #endif
pStrHdr->pszStrings[j] = (TCHAR *)FALLOC( MEMSIZE( wCharsLeft + 1));
while ( wCharsLeft-- ) { #ifdef RLRES32
pStrHdr->pszStrings[j][i] = GetWord( InResFile, lSize);
#else //RLRES32
pStrHdr->pszStrings[j][i] = GetByte( InResFile, lSize);
#endif //RLRES32
++i; } pStrHdr->pszStrings[j][i] = TEXT('\0'); i = 0; } return (pStrHdr); }
/**
* * * Function: ReadInRes. * Reads a block of info from the input resource file, and *. then writes the same info to the ouput resource file. * * * Arguments: * InFile, handle of input file. * OutFile, handle of ouput file. * lSize, number of bytes to Copy. * * * Returns: * * * Errors Codes: * 8, read error. * 9, write error. * * History: * 7/91, Implemented. TerryRu. * 11/91, Bug fix to copy more then 64k blocks. PeterW. * 4/92, Bug fix to copy blocks in smaller chunks to save memory. SteveBl * **/ #define CHUNK_SIZE 5120
void ReadInRes( FILE *InFile, FILE *ResFile, DWORD *plSize ) { if ( *plSize > 0L ) { PBYTE pBuf; size_t cNum; size_t cAmount;
pBuf = (PBYTE)FALLOC( CHUNK_SIZE);
do { cAmount = (*plSize > (DWORD)CHUNK_SIZE ? CHUNK_SIZE : *plSize);
cNum = fread( (void *)pBuf, sizeof( BYTE), cAmount, InFile);
if ( cNum != cAmount ) { QuitT( IDS_ENGERR_09, (LPTSTR)IDS_READ, NULL); }
cNum = fwrite( (void *)pBuf, sizeof( BYTE), cAmount, ResFile);
if ( cNum != cAmount) { QuitT( IDS_ENGERR_09, (LPTSTR)IDS_WRITE, NULL); } *plSize -= cAmount;
} while ( *plSize);
RLFREE( pBuf); } }
/**
* * * Function: TokAccelTable * Reads array of accelerator keys, and writes info to be localized * to the token file. * * * Arguments: * TokeFile, file pointer of token file. * ResHeader, Resource Header for Accelerator resource. This info * is need to generate token id. * pAccelTable, array of accelerator keys. * wcTableEntries, number of key definition in Accelerator table * * * Returns: * Accelerator info to be localized writen to token file. * * Errors Codes: * None. * * History: * 7/91, Implemented. TerryRu. * 01/93 Added support for var length token text strings. MHotchin * **/
void TokAccelTable (FILE *TokFile , RESHEADER ResHeader, ACCELTABLEENTRY * pAccelTable, WORD wcTableEntries) { TOKEN tok; WORD i, l; char szBuf[10];
tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wFlag = 0; tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy( tok.szName, ResHeader.pszName);
for (i = 0; i < wcTableEntries ; i ++) { tok.wFlag = (WORD) pAccelTable[i].fFlags; tok.wID = i;
// The order of wID and wAscii is reverse to the
// oder in the accelerator structure and the .rc file
sprintf( szBuf, "%hu %hu", pAccelTable[i].wID, pAccelTable[i].wAscii);
l = lstrlenA( szBuf) + 1; tok.szText = (TCHAR *)FALLOC( MEMSIZE( l)); #ifdef RLRES32
_MBSTOWCS( (TCHAR *)tok.szText, szBuf, l, l); #else
lstrcpyA(tok.szText, szBuf); #endif
PutToken(TokFile, &tok); RLFREE( tok.szText); } }
/**
* * * Function: TokDialog. * Travers through linked list of the Dialog defintion, and writes any info * which requires localization to the token file. * * * Arguments: * TokFile, file pointer of token file. * ResHeader, Resource header info of dialog resource. This info is needed * to generate the token id. * pDialogHdr, linked list of dialog info. Each dialog control is a node * in the linked list. * * * Returns: * The info requiring localization written to the tok file. * * Errors Codes: * None. * * History: * 7/91. Implemented. TerryRu. * 7/91. Now tokenize all control cordiantes, so they are * maintained during updates. TerryRu. * 8/91. Supported signed coordinates. TerryRu. * 1/93. Now tokenize dlg font names. TerryRu * 01/93 Add support for var length token text MHotchin **/
void TokDialog( FILE * TokFile, RESHEADER ResHeader, DIALOGHEADER *pDialogHdr) { WORD wcDup = 0; WORD *pwIdBuf; WORD i, j = 0, k = 0, l = 0; static CHAR szTmpBuf[256]; static TCHAR szBuf[256]; static TOKEN tok;
*szTmpBuf = '\0'; *szBuf = TEXT('\0');
// tok the dialog caption
tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wID = 0; tok.wFlag = ISCAP; tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy ((TCHAR *)tok.szName , (TCHAR *)ResHeader.pszName);
tok.szText = BinToText( pDialogHdr->pszCaption, lstrlen( pDialogHdr->pszCaption)); PutToken(TokFile, &tok); RLFREE( tok.szText);
// tok the dialog cordinates
// bug fix, cordinates can be signed.
tok.wFlag = (ISCAP) | (ISCOR);
#ifdef RLRES32
sprintf( szTmpBuf, "%4hd %4hd %4hd %4hd", pDialogHdr->x, pDialogHdr->y, pDialogHdr->cx, pDialogHdr->cy);
if ( gfShowClass ) { sprintf( &szTmpBuf[ strlen( szTmpBuf)], " : TDB"); } _MBSTOWCS( szBuf, szTmpBuf, WCHARSIN( sizeof( szBuf)), ACHARSIN( lstrlenA( szTmpBuf ) + 1 )); #else
sprintf( szBuf, "%4hd %4hd %4hd %4hd", pDialogHdr->x, pDialogHdr->y, pDialogHdr->cx, pDialogHdr->cy); #endif
tok.szText = BinToText( szBuf, lstrlen( szBuf));
PutToken(TokFile, &tok); RLFREE( tok.szText);
if (gfExtendedTok) { // toknize dialog fontname, and size
if ( pDialogHdr->lStyle & DS_SETFONT ) { tok.wFlag = ISDLGFONTSIZE; sprintf(szTmpBuf, "%hu", pDialogHdr->wPointSize); l = lstrlenA( szTmpBuf) + 1; tok.szText = (TCHAR *)FALLOC( MEMSIZE( l)); #ifdef RLRES32
_MBSTOWCS( (TCHAR*) tok.szText, szTmpBuf, l, l); #else
strcpy(tok.szText, szTmpBuf); #endif
PutToken(TokFile, &tok); RLFREE( tok.szText);
tok.wFlag = ISDLGFONTNAME; tok.szText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( pDialogHdr->pszFontName) + 1)); lstrcpy( tok.szText, pDialogHdr->pszFontName);
PutToken( TokFile, &tok); RLFREE( tok.szText); tok.szText = NULL; } }
// allocate buffer for for duplicate check
pwIdBuf = (WORD *) FALLOC((DWORD) pDialogHdr->wNumberOfItems * sizeof(WORD));
for (i = 0; i < (WORD) pDialogHdr->wNumberOfItems; i ++) { if (isdup ((WORD)pDialogHdr->pCntlData[i].dwID, pwIdBuf, (WORD)j)) { tok.wID = (USHORT)wcDup++; tok.wFlag = ISDUP; } else { // wid is unique so store in buffer for dup check
pwIdBuf[j++] = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wID = (USHORT)pDialogHdr->pCntlData[i].dwID; tok.wFlag = 0; }
if (pDialogHdr->pCntlData[i].pszDlgText[0]) { tok.szText = BinToText( pDialogHdr->pCntlData[i].pszDlgText, lstrlen( (TCHAR *)pDialogHdr->pCntlData[i].pszDlgText));
PutToken(TokFile, &tok); RLFREE( tok.szText); }
// now do the dialog corrdinates,
// bug fix, cordinates can be signed.
#ifdef RLRES32
sprintf( szTmpBuf, "%4hd %4hd %4hd %4hd", pDialogHdr->pCntlData[i].x, pDialogHdr->pCntlData[i].y, pDialogHdr->pCntlData[i].cx, pDialogHdr->pCntlData[i].cy);
_MBSTOWCS( szBuf, szTmpBuf, WCHARSIN( sizeof ( szBuf)), ACHARSIN( lstrlenA( szTmpBuf ) + 1));
if (gfExtendedTok) if ( (pDialogHdr->pCntlData[i].bClass_Flag == IDFLAG) && ((pDialogHdr->pCntlData[i].bClass == STATIC) || (pDialogHdr->pCntlData[i].bClass == EDIT) ) ) { TCHAR *pszCtrl[3] = { TEXT("LEFT"), TEXT("CENTER"), TEXT("RIGHT") }; TCHAR *pszAlign = NULL; DWORD dwStyle = pDialogHdr->pCntlData[i].lStyle;
if ( pDialogHdr->pCntlData[i].bClass == STATIC ) { // STATIC class alignment values are constants
// not flags, so we handle them differently
// than we do for the EDIT class below.
dwStyle &= (SS_LEFT|SS_CENTER|SS_RIGHT);
if ( dwStyle == SS_RIGHT ) { pszAlign = pszCtrl[2]; } else if ( dwStyle == SS_CENTER ) { pszAlign = pszCtrl[1]; } else if ( dwStyle == SS_LEFT ) { pszAlign = pszCtrl[0]; } } else { // Dealing with an EDIT class
if ( dwStyle & ES_RIGHT ) { pszAlign = pszCtrl[2]; } else if ( dwStyle & ES_CENTER ) { pszAlign = pszCtrl[1]; } else if ( dwStyle & ES_LEFT ) { pszAlign = pszCtrl[0]; } }
if ( pszAlign ) { _stprintf( &szBuf[ _tcslen( szBuf)], TEXT(" ( %s ) "), pszAlign); } }
if ( gfShowClass ) { if ( pDialogHdr->pCntlData[i].bClass_Flag == IDFLAG ) { TCHAR *pszCtrl = TEXT("???"); //... DLG box control class
switch ( pDialogHdr->pCntlData[i].bClass ) { case BUTTON: { WORD wTmp;
wTmp = (WORD)(pDialogHdr->pCntlData[i].lStyle & 0xffL);
switch ( wTmp ) {
case BS_PUSHBUTTON: case BS_DEFPUSHBUTTON:
pszCtrl = TEXT("BUT"); break;
case BS_CHECKBOX: case BS_AUTOCHECKBOX: case BS_3STATE: case BS_AUTO3STATE:
pszCtrl = TEXT("CHX"); break;
case BS_RADIOBUTTON: case BS_AUTORADIOBUTTON:
pszCtrl = TEXT("OPT"); break;
case BS_GROUPBOX: case BS_USERBUTTON: case BS_OWNERDRAW: case BS_LEFTTEXT: default:
pszCtrl = TEXT("DIA"); break;
} //... END switch( wTmp )
break; } case STATIC:
#ifdef DBCS
//Special hack
//I will remove this code later.
//This code is for fix code between 1.84 and 1.85(STATIC alignment problem)
{ WORD wTmp;
wTmp = (WORD)(pDialogHdr->pCntlData[i].lStyle & (SS_LEFT|SS_CENTER|SS_RIGHT)); if ( (wTmp==SS_CENTER) || (wTmp==SS_LEFT) || (wTmp==SS_RIGHT) ) { pszCtrl = TEXT("TXB"); } else { pszCtrl = TEXT("ICO"); } break; } #else // not DBCS
pszCtrl = TEXT("TXB"); break; #endif // DBCS
default:
pszCtrl = TEXT("DIA"); break;
} //... END switch ( pDialogHdr->pCntlData[i].bClass )
wsprintf( &szBuf[ lstrlen( szBuf)], TEXT(" : %s"), pszCtrl); } else { wsprintf( &szBuf[ lstrlen( szBuf)], TEXT(" : \"%s\""), pDialogHdr->pCntlData[i].pszClass); } }
#else
sprintf(szBuf, "%4hd %4hd %4hd %4hd", pDialogHdr->pCntlData[i].x, pDialogHdr->pCntlData[i].y, pDialogHdr->pCntlData[i].cx, pDialogHdr->pCntlData[i].cy); #endif
tok.wFlag |= ISCOR;
tok.szText = BinToText( szBuf, lstrlen( (TCHAR *)szBuf)); PutToken(TokFile, &tok); RLFREE( tok.szText); tok.szText = NULL; } RLFREE( pwIdBuf); pwIdBuf = NULL; }
/**
* * * Function: TokMenu, * Travers the linked list of the Menu definition, and writes any info * requiring localization to the token file. * * * Arguments: * TokFile, file pointer of token file. * ResHeader, Resource header of Menu info. Need to generate token ids. * pMenuHdr, Header of the menu used to access the linked list of token info. * * Returns: * TokenFile contain all info requiring localization. * * Errors Codes: * None. * * History: * 7/91, Implemented. TerryRu. * 01/93 Added support for var length token text strings. MHotchin * **/
void TokMenu(FILE *TokFile , RESHEADER ResHeader, MENUHEADER *pMenuHdr) { TOKEN tok; static WORD wcPopUp = 0; MENUITEM *pMenuItem;
pMenuItem = pMenuHdr->pMenuItem;
tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
while (pMenuItem) { // if Menu Item is a seperator skip it
if (*pMenuItem->szItemText) { tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID;
// check for the popup menu items
if ((pMenuItem->fItemFlags & MFR_POPUP) && pMenuHdr->fMenuEx) { tok.wID = (pMenuItem->dwMenuID == 0 || pMenuItem->dwMenuID == 0x0000ffff) ? (USHORT)pMenuItem->dwMenuID : 0x8000 + wcPopUp++; tok.wFlag = ISPOPUP; } else if (pMenuItem->fItemFlags & POPUP) { tok.wID = wcPopUp++; tok.wFlag = ISPOPUP; } else { tok.wID = (USHORT)pMenuItem->dwMenuID; tok.wFlag = 0; } lstrcpy ((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
tok.szText = BinToText( pMenuItem->szItemText, lstrlen( (TCHAR *)pMenuItem->szItemText)); PutToken (TokFile, &tok); RLFREE( tok.szText); } pMenuItem = pMenuItem->pNextItem; } }
/**
* * * Function: TokString * Write the 16 strings contained in the string block. * * * Arguments: * TokFile, file pointer of Token File. * ResHeader, Resource header info of String block. * pStrHdr, Array of 16 strings making up portion of the string table. * * Returns: * Strings written to the Token File. * * Errors Codes: * None. * * History: * 7/91, Implemented. TerryRu. * 01/93 Added support for var length token text strings. MHotchin * **/
void TokString( FILE * TokFile, RESHEADER ResHeader, STRINGHEADER * pStrHdr) { // int nLen;
TOKEN tok; BYTE i;
for ( i = 0; i < 16; i++ ) { tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wID = i; tok.wFlag = 0; tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy( (TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
// nLen = lstrlen( (TCHAR *)pStrHdr->pszStrings[i]); //DHW_TOOLONG
tok.szText = BinToText( (TCHAR *)pStrHdr->pszStrings[i], pStrHdr->wChars[i]);
PutToken( TokFile, &tok); RLFREE( tok.szText); } }
#ifdef RLRES32
//................................................................
//...
//... Move to start of value field in version resource blocks
//... and adjust remaining-data-sizes accordingly.
PVERBLOCK MoveAlongVer(
PVERBLOCK pVerData, //... Start of current version block
WORD *pw1, //... First word to decrement
WORD *pw2, //... Second word to decrement
WORD *pw3) //... Third word to decrement
{ WORD wLen; PBYTE pData = (PBYTE)pVerData;
wLen = DWORDUP( pVerData->wLength);
pData += DWORDUP( wLen);
DECWORDBY( pw1, wLen); DECWORDBY( pw2, wLen); DECWORDBY( pw3, wLen);
return ( (PVERBLOCK)pData); }
//....................................................................
TCHAR *GetVerValue( PVERBLOCK pVerData) { WORD wLen = sizeof( VERBLOCK);
//... sizeof(VERBLOCK) already includes
//... the size of a WCHAR so we do not
//... need to add 1 to length of the key.
wLen += (WORD) (BYTESINSTRING( pVerData->szKey)); wLen = DWORDUP( wLen); //... Possible DWORD padding
return ( (TCHAR *)((PBYTE)pVerData + wLen)); }
//....................................................................
#endif //... RLRES32
/**
* * * Function: TokResVer * Reads through the Version Info blocks, and writes any info requiring * localization to the token file. * * * Arguments: * TokeFile, file pointer of token file. * ResHeader, Resource Header info for version stamping. Need to generate * the token IDs. * * Returns: * * Errors Codes: * 1, info written to token file. * * History: * 11/91. Implemented. TerryRu. * 10/92. Added RLRES32 version DaveWi * 01/93 Added support for var length token text strings. MHotchin * **/
#ifdef RLRES32
int TokResVer(
FILE *fpTokFile, //... Output token file
RESHEADER ResHeader, //... Resource header of version resource
VERBLOCK *pVerData, //... Data to tokenize
WORD wDataLen) //... # bytes in pVerData
{ TOKEN Tok; BOOL fInStringInfo = FALSE; //... TRUE if reading StringFileInfo
WORD wTokNum = 0; //... Put into Tok.wID field
WORD wTokContinueNum = 0; //... Put into Tok.wFlag field
if (wDataLen == 0 || wDataLen == (WORD)-1) { return (-1); //... No data to tokenize
} //... Fill in static part of TOKEN struct
Tok.wType = ResHeader.wTypeID; Tok.wName = IDFLAG; Tok.szName[0] = TEXT('\0'); Tok.szType[0] = TEXT('\0'); Tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
//... Make a token for each string found
while (wDataLen > 0) { WORD wRC;
//... Start of a StringFileInfo block?
wRC =(WORD)_tcsncmp((TCHAR *)pVerData->szKey, (TCHAR *)STRINGFILEINFO, min(wDataLen, (WORD)STRINGFILEINFOLEN));
if (wRC == SAME) { WORD wStringInfoLen = 0; //... # of bytes in StringFileInfo
WORD wLen = 0;
//... Get # of bytes in this StringFileInfo
//... (Length of value is always 0 here)
wStringInfoLen = pVerData->wLength;
//... Move to start of first StringTable blk.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK) - sizeof(WCHAR) + MEMSIZE( STRINGFILEINFOLEN)));
pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen); DECWORDBY(&wDataLen, wLen); DECWORDBY(&wStringInfoLen, wLen);
while (wStringInfoLen > 0) { WORD wStringTableLen = 0;
//... Get # of bytes in this StringTable
//... (Length of value is always 0 here)
wStringTableLen = pVerData->wLength;
//... Copy Language BLOCK Info key
//... into Token name
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)LANGUAGEINFO);
//... Copy lang string into token
Tok.szText = (TCHAR *) FALLOC(MEMSIZE(LANGSTRINGLEN+1)); CopyMemory( Tok.szText, pVerData->szKey, LANGSTRINGLEN * sizeof ( TCHAR));
Tok.szText[ LANGSTRINGLEN] = TEXT('\0');
Tok.wID = wTokNum++; Tok.wFlag = 0;
PutToken(fpTokFile, &Tok); RLFREE( Tok.szText);
//... Move to start of first String.
wLen = DWORDUP(sizeof(VERBLOCK) - sizeof(WCHAR) + MEMSIZE( LANGSTRINGLEN));
pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen);
DECWORDBY(&wDataLen, wLen); DECWORDBY(&wStringInfoLen, wLen); DECWORDBY(&wStringTableLen, wLen);
while (wStringTableLen > 0) { //... Is value a string?
if (pVerData->wType == VERTYPESTRING) { Tok.wID = wTokNum++;
lstrcpy( (TCHAR *)Tok.szName, (TCHAR *)pVerData->szKey); Tok.szText = BinToText( GetVerValue( pVerData), lstrlen( GetVerValue( pVerData)));
PutToken(fpTokFile, &Tok); RLFREE( Tok.szText); } //... Move to start of next String.
pVerData = MoveAlongVer(pVerData, &wDataLen, &wStringInfoLen, &wStringTableLen);
} //... END while (wStringTableLen)
} //... END while (wStringInfoLen)
} else { if (_tcsncmp((TCHAR *)pVerData->szKey, (TCHAR *)VARFILEINFO, min(wDataLen, (WORD)VARFILEINFOLEN)) == SAME) { WORD wVarInfoLen = 0; //... # of bytes in VarFileInfo
WORD wLen = 0;
//... Get # of bytes in this VarFileInfo
//... (Length of value is always 0 here)
wVarInfoLen = pVerData->wLength;
//... Move to start of first Var.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK) - sizeof(WCHAR) + MEMSIZE( VARFILEINFOLEN))); pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen);
DECWORDBY(&wDataLen, wLen); DECWORDBY(&wVarInfoLen, wLen);
while (wVarInfoLen > 0) { if (_tcsncmp(pVerData->szKey, TRANSLATION, min( wDataLen, (WORD)TRANSLATIONLEN)) == SAME) { PBYTE pValue = NULL; WORD wTransLen = 0; USHORT uByte1 = 0; USHORT uByte2 = 0; UINT uLen = 0;
wTokContinueNum = 0;
//... How many bytes are we to tokenize?
wTransLen = pVerData->wValueLength;
//... Where are those bytes?
pValue = (PBYTE)GetVerValue(pVerData);
//... Copy VarFileInfo into Token
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)pVerData->szKey);
//... Allocate a buffer for a space-separated
//... list of the lang ID's in this vresion res.
*szDHW = '\0';
while ( wTransLen >= TRANSDATALEN ) { //... Write translation language id by
//... reversing byte pairs so the id looks
//... like the language id string. This will
//... have to be undone in PutResVer().
uByte1 = *pValue; uByte2 = *(pValue + 1);
sprintf( &szDHW[ lstrlenA( szDHW)], "%02hx%02hx", uByte2, //... Reverses byte order to
uByte1); //... be like transltn str.
//... Move to next possible translation value
wTransLen -= TRANSDATALEN;
if ( wTransLen >= TRANSDATALEN ) { pValue += TRANSDATALEN; strcat( szDHW, " "); //... white-space sep
} } //... END while ( wTransLen ...
uLen = lstrlenA( szDHW) + 1; Tok.szText = (TCHAR *)FALLOC( MEMSIZE( uLen)); _MBSTOWCS( (TCHAR *)Tok.szText, szDHW, uLen, (UINT)-1);
Tok.wID = wTokNum; Tok.wFlag = wTokContinueNum++;
PutToken( fpTokFile, &Tok);
RLFREE( Tok.szText); } //... END if (_tcsncmp( ...
//... Move to start of next Var info block.
pVerData = MoveAlongVer(pVerData, &wDataLen, &wVarInfoLen, NULL);
} //... END while (wVarInfoLen)
} else { QuitT( IDS_ENGERR_14, (LPTSTR)IDS_INVVERBLK, NULL); } } } //... END while (wDataLen)
return (0); }
#else //... RLRES32
int TokResVer(FILE * TokFile, RESHEADER ResHeader, VERBLOCK *pVerBlk) { TCHAR szLangIdBuf[20]; TCHAR szCodePageIdBuf[20]; #ifdef RLRES32
CHAR szTmpBuf[20]; #endif
WORD wcLang = 0, wcBlock = 0; TOKEN tok; VERBLOCK *pCurBlk; TCHAR *pszStr; DWORD *pdwVal; int wTotLen, nHeadLen, wBlkLen;
// the count fields are int because count may go negative
// because the last DWORD alignment is not counted in the
// byte count.
// Fill in static part of TOKEN struct
tok.wType = ResHeader.wTypeID; tok.wName = IDFLAG; tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
wTotLen = DWORDUP(pVerBlk->nTotLen);
tok.wID = wcBlock; pszStr = pVerBlk->szKey; nHeadLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= nHeadLen; pCurBlk = (VERBLOCK *) ((TCHAR *) pVerBlk + nHeadLen);
while (wTotLen > 0) { // For string file tables we localize the key field
tok.wFlag = ISKEY; wBlkLen = DWORDUP(pCurBlk->nTotLen); pszStr = pCurBlk->szKey;
tok.szText = BinToText( pszStr, lstrlen((TCHAR *)pszStr));
lstrcpy((TCHAR *)tok.szName, TEXT("Language Info")); tok.wID = wcBlock;
PutToken(TokFile, &tok); RLFREE(tok.szText);
// Get offset to next block;
nHeadLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
// Update counter vars
wTotLen -= wBlkLen; wBlkLen -= nHeadLen;
// set pointer to next ver block
pCurBlk = (VERBLOCK*) ((TCHAR *) pCurBlk + nHeadLen);
// For string blocks we localize the value field.
tok.wFlag = ISVAL;
// Now output the tokens in String Block
while (wBlkLen>0) { pszStr = pCurBlk->szKey; lstrcpy((TCHAR *)tok.szName, (TCHAR *)pszStr); pszStr = (TCHAR *) pCurBlk+4+DWORDUP(lstrlen((TCHAR *)pszStr)+1);
tok.szText = BinToText( pszStr, lstrlen((TCHAR *)pszStr)); PutToken(TokFile, &tok); RLFREE(tok.szText);
wBlkLen -= DWORDUP(pCurBlk->nTotLen); pCurBlk = (VERBLOCK *) ((TCHAR *) pCurBlk + DWORDUP(pCurBlk->nTotLen)); } wcBlock++; }
// Skip past Head of VarInfoBlock
wTotLen = DWORDUP(pCurBlk->nTotLen);
pszStr = pCurBlk->szKey; nHeadLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1); wTotLen -= nHeadLen; pCurBlk = (VERBLOCK *)((TCHAR *) pCurBlk + nHeadLen);
wcLang = 0;
// In Var File blocks we localize the value fields.
tok.wFlag = ISVAL;
while (wTotLen > 0) { TCHAR szTemp[256];
pszStr = pCurBlk->szKey; tok.wID = wcLang; lstrcpy((TCHAR *)tok.szName, TEXT("Translation")); pdwVal = (DWORD *)((TCHAR *) pCurBlk + 4 + DWORDUP(lstrlen((TCHAR *)pszStr) + 1)); #ifdef RLRES32
_itoa(HIWORD(*pdwVal) , szTmpBuf, 16); _MBSTOWCS( szLangIdBuf, szTmpBuf, WCHARSIN( sizeof( szLangIdBuf)), ACHARSIN( strlen( szTmpBuf ) + 1)); #else
_itoa(HIWORD(*pdwVal) , szLangIdBuf, 16); #endif
#ifdef RLRES32
_itoa(LOWORD(*pdwVal), szTmpBuf, 16); _MBSTOWCS( szCodePageIdBuf, szTmpBuf, WCHARSIN( sizeof( szCodePageIdBuf)), ACHARSIN( strlen( szTmpBuf ) + 1)); #else
_itoa(LOWORD(*pdwVal), szCodePageIdBuf, 16); #endif
// Construct Token Text
// Note leading zeros gets lost in itoa translation
lstrcpy((TCHAR *)szTemp, TEXT("0")); _tcscat((TCHAR *)szTemp, _tcsupr((TCHAR *)szCodePageIdBuf)); _tcscat((TCHAR *)szTemp, TEXT("0")); _tcscat((TCHAR *)szTemp, _tcsupr((TCHAR *)szLangIdBuf));
tok.szText = BinToText( szTemp, lstrlen((TCHAR *)szTemp)); PutToken(TokFile, &tok); RLFREE(tok.szText); wcLang ++; wTotLen -= DWORDUP(pCurBlk->nTotLen); pCurBlk = (VERBLOCK *) ((BYTE *) pCurBlk + DWORDUP(pCurBlk->nTotLen)); } return (1); }
#endif //... RLRES32
/**
* * * Function: UpdateResSize * Preforms the Resource Header size fixup, once the size of * the localized resource block is determined. * * * Arguments: * OutResFile, File pointer of localized resource file. * pResSizePos, file location of size file, of the resoure header. * lSize, size of the localized resource. * * Returns: * The size field fixed up to the value specfied in the lsize. * * Errors Codes: * TRUE, fixup sucessfull. * Result of fsetpos, and fgetpos call. * * History: * * **/
WORD UpdateResSize (FILE * OutResFile, fpos_t *pResSizePos, DWORD lSize) { WORD rc; fpos_t tResSizePos;
if ((rc = (WORD) fgetpos (OutResFile, &tResSizePos)) != 0) { return (rc); }
if ((rc = (WORD) fsetpos (OutResFile, pResSizePos)) != 0) { return (rc); }
PutdWord(OutResFile, lSize, NULL);
if ((rc = (WORD) fsetpos (OutResFile, &tResSizePos)) != 0) { return (rc); }
return (TRUE) ; }
/**
* * * Function: * * * Arguments: * * Returns: * * Errors Codes: * * History: * 01/93 Added support for var length token text strings. MHotchin * **/
void PutAccelTable(FILE *OutResFile, FILE *TokFile, RESHEADER ResHeader, ACCELTABLEENTRY *pAccelTable, WORD wcAccelEntries)
{ fpos_t ResSizePos = 0; TOKEN tok; WORD wcCount = 0; DWORD lSize = 0L; TCHAR pErrBuf[MAXINPUTBUFFER]; #ifdef RLRES32
CHAR szTmpBuf[30]; #endif
TCHAR *cpAscii, *cpID;
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) { QuitT( IDS_ENGERR_06, (LPTSTR)IDS_ACCELKEY, NULL); }
lSize = 0L;
// Prep for find token call
tok.wType = ResHeader.wTypeID; tok.wName = ResHeader.wNameID; tok.wID = 0; tok.wFlag = 0; tok.wReserved = ST_TRANSLATED;
lstrcpy( tok.szName, ResHeader.pszName);
for (wcCount = 0; wcCount < wcAccelEntries; wcCount++) { tok.wID = wcCount; tok.wFlag = (WORD) pAccelTable[wcCount].fFlags; tok.szText = NULL;
if (!FindToken(TokFile, &tok, ST_TRANSLATED)) {
ParseTokToBuf(pErrBuf, &tok); QuitT( IDS_ENGERR_05, pErrBuf, NULL); }
tok.wReserved = ST_TRANSLATED;
cpID = (TCHAR *)tok.szText; cpAscii = _tcschr((TCHAR *)tok.szText, TEXT(' ')); (*cpAscii) = '\0'; cpAscii++;
#ifdef RLRES16
#ifndef PDK2
PutByte (OutResFile, (BYTE) pAccelTable[wcCount].fFlags, &lSize);
#else // PDK2
PutWord (OutResFile, (WORD) pAccelTable[wcCount].fFlags, &lSize);
#endif // PDK2
#else // RLRES16
PutWord (OutResFile, (WORD) pAccelTable[wcCount].fFlags, &lSize);
#endif // RLRES16
#ifdef RLRES32
_WCSTOMBS( szTmpBuf, cpAscii, ACHARSIN( sizeof( szTmpBuf)), lstrlen( cpAscii ) + 1 ); PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
_WCSTOMBS( szTmpBuf, cpID, ACHARSIN( sizeof( szTmpBuf)), lstrlen( cpID ) + 1 ); PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
#else // RLRES32
PutWord (OutResFile, (WORD) atoi(cpAscii), &lSize); PutWord (OutResFile, (WORD) atoi(cpID), &lSize);
#endif // RLRES32
#ifdef RLRES32
PutWord (OutResFile, pAccelTable[wcCount].wPadding, &lSize); #endif
RLFREE( tok.szText);
} // for
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) { QuitT( IDS_ENGERR_07, (LPTSTR)IDS_ACCELKEY, NULL); } } // PutAccelTable
void CopyRes(
FILE *fpInResFile, FILE *fpOutResFile, RESHEADER *pResHeader, fpos_t *pResSizePos) { DWORD dwTmp = 0L;
PutResHeader( fpOutResFile, *pResHeader, pResSizePos, &dwTmp);
ReadInRes( fpInResFile, fpOutResFile, (DWORD *)&(pResHeader->lSize));
#ifdef RLRES32
DWordUpFilePointer( fpInResFile, MYREAD, ftell( fpInResFile), NULL);
DWordUpFilePointer( fpOutResFile, MYWRITE, ftell( fpOutResFile), NULL);
#endif
}
/////////////////////////////
// GetDlgInit
//
// VC++ uses a new resource type, DLGINIT (#240) when storing the
// initial contents of a list box. The data for this resource type
// is unaligned and containg non-Unicode strings. This function will
// read the resource data from the resource file pfInRes into a linked
// list of structures and will return a pointer to the head of that list.
// The parameter pdwSize contains the size of the resource as read from
// the resources associated resource header prior to this function
// being called.
// NOTE: The first entry in the list is aligned so it is treated
// slightly differently than are the remaining entries.
PDLGINITDATA GetDlgInit( FILE * pfInRes, DWORD *pdwSize) { PDLGINITDATA pList = NULL; PDLGINITDATA pListEntry = NULL; WORD wTmp = 0;
while ( *pdwSize > sizeof( DWORD) + 2 * sizeof( WORD) ) { if ( pList ) { // allocate the next entry in the list
pListEntry->pNext = (PDLGINITDATA)FALLOC( sizeof( DLGINITDATA)); pListEntry = pListEntry->pNext; } else { // allocate the head of the list
pList = (PDLGINITDATA)FALLOC( sizeof( DLGINITDATA)); pListEntry = pList; } // save the first two WORD fields of the data
pListEntry->wControlID = GetWord( pfInRes, pdwSize); pListEntry->wMessageNumber = GetWord( pfInRes, pdwSize); // get the string's length (incl nul terminator)
pListEntry->dwStringLen = GetdWord( pfInRes, pdwSize); // get the string
pListEntry->pszString = FALLOC( pListEntry->dwStringLen);
for ( wTmp = 0; (pListEntry->pszString[ wTmp] = GetByte( pfInRes, pdwSize)); ++wTmp ) ; // empty loop
} // Skip the trailing zero-value WORD
SkipBytes( pfInRes, pdwSize); #ifdef RLRES32
DWordUpFilePointer( pfInRes, MYREAD, ftell( pfInRes), NULL); #endif
return ( pList); }
//////////////////////////////
// TokDlgInit
//
// Make tokens in pTokFile out of the data in the pDlgInit linked list.
void TokDlgInit( FILE *pfTokFile, RESHEADER ResHeader, PDLGINITDATA pDlgInit) { int nLen = 0; WORD wCount = 0; static TOKEN Tok; #ifdef UNICODE
static TCHAR szTmpBuf[ 256]; #else
PCHAR szTmpBuf = NULL; #endif
ZeroMemory( &Tok, sizeof( Tok));
Tok.wType = ResHeader.wTypeID; Tok.wName = ResHeader.wNameID; Tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED); lstrcpy( Tok.szName, ResHeader.pszName);
while ( pDlgInit ) { Tok.wID = wCount++; Tok.wFlag = 0; #ifdef UNICODE
nLen = _MBSTOWCS( szTmpBuf, pDlgInit->pszString, WCHARSIN( sizeof( szTmpBuf)), (UINT)-1); #else
nLen = strlen( pDlgInit->pszString); szTmpBuf = pDlgInit->pszString; #endif
Tok.szText = BinToTextW( szTmpBuf, nLen);
PutToken( pfTokFile, &Tok); RLFREE( Tok.szText); pDlgInit = pDlgInit->pNext; } }
////////////////////////////
// PutDlgInit
//
// Create a new resource in pfOutRes using the data stored in pDlgInit
// and the token text in the pfTokFile.
void PutDlgInit( FILE *pOutResFile, FILE *pTokFile, RESHEADER ResHeader, PDLGINITDATA pDlgInit) { fpos_t ResSizePos = 0; TOKEN Tok; DWORD lSize = 0L; PCHAR pszTmp = NULL;
if ( PutResHeader( pOutResFile, ResHeader , &ResSizePos, &lSize)) { QuitT( IDS_ENGERR_06, TEXT("DLGINIT"), NULL); } lSize = 0L;
// Prep for find token call
Tok.wType = ResHeader.wTypeID; Tok.wName = ResHeader.wNameID; Tok.wID = 0; Tok.wFlag = 0; Tok.wReserved = ST_TRANSLATED;
lstrcpy( Tok.szName, ResHeader.pszName);
while ( pDlgInit ) { Tok.szText = NULL;
if ( ! FindToken( pTokFile, &Tok, ST_TRANSLATED)) { ParseTokToBuf( (LPTSTR)szDHW, &Tok); QuitT( IDS_ENGERR_05, (LPTSTR)szDHW, NULL); } Tok.wReserved = ST_TRANSLATED; Tok.wID++; // Write out the two unchanged WORD fields
PutWord( pOutResFile, pDlgInit->wControlID, &lSize); PutWord( pOutResFile, pDlgInit->wMessageNumber, &lSize); // write the length of the new string (incl nul)
_WCSTOMBS( szDHW, Tok.szText, DHWSIZE, (UINT)-1); PutdWord( pOutResFile, strlen( szDHW) + 1, &lSize); // write the new string (incl nul)
for ( pszTmp = szDHW; *pszTmp; ++pszTmp ) { PutByte( pOutResFile, *pszTmp, &lSize); } PutByte( pOutResFile, '\0', &lSize);
pDlgInit = pDlgInit->pNext; } // write the trailing zero-value WORD
PutWord( pOutResFile, 0, &lSize);
if ( ! UpdateResSize( pOutResFile, &ResSizePos, lSize) ) { QuitT( IDS_ENGERR_07, TEXT("DLGINIT"), NULL); } #ifdef RLRES32
DWordUpFilePointer( pOutResFile, MYWRITE, ftell( pOutResFile), NULL); #endif
}
//////////////////////////////
// ClearDlgInitData
//
// Free the memory allocated for the DlgInitData linked list in GetDlgInit().
void ClearDlgInitData( PDLGINITDATA pDlgInit) { while ( pDlgInit ) { PDLGINITDATA pTmp = pDlgInit->pNext; RLFREE( pDlgInit->pszString); RLFREE( pDlgInit); pDlgInit = pTmp; } }
|