#include #include #include #include //#include #include //#include //#include //#include #include #ifdef RLDOS #include "dosdefs.h" #else //RLDOS #include #include "windefs.h" #endif //RLDOS #include "resread.h" #include "restok.h" #include "custres.h" #ifdef RLRES32 #include "exentres.h" #include "reswin16.h" #else //RLRES32 #include "exe2res.h" #endif //RLRES32 UCHAR szDHW[ DHWSIZE]; //... Common temporary buffer char * gszTmpPrefix = "$RLT"; //... Temporary name prefix BOOL gbMaster = FALSE; //... TRUE if Working in Master project BOOL gfReplace = TRUE; //... FALSE if appending new language to exe BOOL gbShowWarnings = FALSE; //... Display warnining messages if TRUE #ifdef _DEBUG PMEMLIST pMemList = NULL; #endif static BOOL ShouldBeAnExe( CHAR *); static BOOL NotExistsOrIsEmpty( PCHAR szTargetTokFile); /** * * * Function: DWORDfpUP * Move the file pointer to the next 32 bit boundary. * * * Arguments: * Infile: File pointer to seek * plSize: Address of Resource size var * * Returns: * Number of padding to next 32 bit boundary, and addjusts resource size var * * Errors Codes: * -1, fseek failed * * History: * 10/11/91 Implemented TerryRu * * **/ DWORD DWORDfpUP(FILE * InFile, DWORD *plSize) { DWORD tPos; DWORD Align; tPos = (ftell(InFile)); Align = DWORDUP(tPos); *plSize -= (Align - tPos); fseek( InFile, Align, SEEK_SET); return ( Align - tPos); } /* * * Function GetName, * Copies a name from the OBJ file into the ObjInfo Structure. * */ void GetName( FILE *infile, TCHAR *szName , DWORD *lSize) { WORD i = 0; do { #ifdef RLRES16 szName[ i ] = GetByte( infile, lSize); #else szName[ i ] = GetWord( infile, lSize); #endif } while ( szName[ i++ ] != TEXT('\0') ); } /* * * Function MyAlloc: * Memory allocation routine with error checking. * */ #ifdef _DEBUG PBYTE MyAlloc( DWORD dwSize, LPSTR pszFile, WORD wLine) #else PBYTE MyAlloc( DWORD dwSize) #endif { PBYTE ptr = NULL; HGLOBAL hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, (size_t)((dwSize > 0) ? dwSize : sizeof( TCHAR))); if ( hMem == NULL ) { QuitT( IDS_ENGERR_11, NULL, NULL); } else { ptr = GlobalLock( hMem); } #ifdef _DEBUG { PMEMLIST pTmpMem = (PMEMLIST)GlobalAlloc( GPTR, sizeof( MEMLIST)); pTmpMem->pNext = pMemList; pMemList = pTmpMem; lstrcpyA( pMemList->szMemFile, pszFile); pMemList->wMemLine = wLine; pMemList->pMem = ptr; } #endif // _DEBUG return ( ptr); // memory allocation okay. } //.......................................................................... //ppc cause access violation void MyFree( void *UNALIGNED*p) { if ( p && *p ) { #ifdef _DEBUG FreeMemListItem( *p, NULL); #else HGLOBAL hMem = GlobalHandle( (HANDLE)*p); GlobalUnlock( hMem); GlobalFree( hMem); #endif // _DEBUG *p = NULL; } } #ifdef _DEBUG void FreeMemList( FILE *pfMemFile) { while ( pMemList ) { FreeMemListItem( pMemList->pMem, pfMemFile); } } void FreeMemListItem( void *p, FILE *pfMemFile) { if ( pMemList && p ) { PMEMLIST pThisMem = NULL; PMEMLIST pNextMem = NULL; PMEMLIST pPrevMem = NULL; for ( pThisMem = pMemList; pThisMem; pThisMem = pNextMem ) { pNextMem = pThisMem->pNext; if ( pThisMem->pMem == p ) { HGLOBAL hMem = NULL; if ( pfMemFile ) { fprintf( pfMemFile, "%u\t%s\n", pThisMem->wMemLine, pThisMem->szMemFile); } hMem = GlobalHandle( p); GlobalUnlock( hMem); GlobalFree( hMem); GlobalFree( pThisMem); if ( pPrevMem ) { pPrevMem->pNext = pNextMem; } else { pMemList = pNextMem; } break; } pPrevMem = pThisMem; } } } #endif // _DEBUG /* * * Function MyReAlloc * * Re-allocate memory with error checking. * * History: * 01/21/93 MHotchin Implemented. * */ #ifdef _DEBUG PBYTE MyReAlloc( PBYTE pOldMem, //... Current ptr to buffer DWORD cSize, //... New size for buffer LPSTR pszFile, WORD wLine) #else PBYTE MyReAlloc( PBYTE pOldMem, //... Current ptr to buffer DWORD cSize) //... New size for buffer #endif // _DEBUG { PBYTE ptr = NULL; HGLOBAL hMem = NULL; hMem = GlobalHandle( pOldMem); if ( hMem == NULL ) { QuitT( IDS_ENGERR_11, NULL, NULL); } if ( GlobalUnlock( hMem) || GetLastError() != NO_ERROR ) { QuitT( IDS_ENGERR_11, NULL, NULL); } hMem = GlobalReAlloc( hMem, cSize, GMEM_MOVEABLE | GMEM_ZEROINIT); if ( hMem == NULL ) { QuitT( IDS_ENGERR_11, NULL, NULL); } ptr = GlobalLock( hMem); #ifdef _DEBUG if ( ptr != pOldMem ) { PMEMLIST pThisMem = NULL; PMEMLIST pNextMem = NULL; for ( pThisMem = pMemList; pThisMem; pThisMem = pThisMem->pNext ) { if ( pThisMem->pMem == pOldMem ) { pThisMem->pMem = ptr; break; } } } #endif // _DEBUG return ( ptr); } /* * * Function GetByte: * Reads a byte from the input file stream, and checks for EOF. * */ BYTE GetByte(FILE *pInFile, DWORD *pdwSize) { register int n; if ( pdwSize ) { (*pdwSize)--; } n = fgetc( pInFile); if ( n == EOF ) { if ( feof( pInFile) ) { exit(-1); } } return ( (BYTE)n); } /* * * Function UnGetByte: * * Returns the character C into the input stream, and updates the Record Length. * * Calls: * ungetc, To return character * DiffObjExit, If unable to insert the character into the input stream * * Caller: * GetFixUpP, * */ void UnGetByte(FILE *infile, BYTE c, DWORD *lSize) { if (lSize) { (*lSize)++; } if (ungetc(c, infile)== EOF) { exit (-1); } // c put back into input stream } /* * * Function UnGetWord: * * Returns the word C into the input stream, and updates the Record Length. * * Calls: * * Caller: * */ void UnGetWord(FILE *infile, WORD c, DWORD *lSize) { long lCurrentOffset; if (lSize) { (*lSize) += 2; } lCurrentOffset = ftell(infile); if (fseek(infile, (lCurrentOffset - 2L) , SEEK_SET)) { exit (-1); } } /* * * Function SkipBytes: * Reads and ignores n bytes from the input stream * */ void SkipBytes(FILE *infile, DWORD *pcBytes) { if (fseek(infile, (DWORD) *pcBytes, SEEK_CUR) == -1L) { exit (-1); } *pcBytes=0; } /* * Function GetWord: * Reads a WORD from the RES file. * */ WORD GetWord(FILE *infile, DWORD *lSize) { // Get low order byte register WORD lobyte; lobyte = GetByte(infile, lSize); return (lobyte + (GetByte(infile, lSize) << BYTELN)); } /* * * Function GetDWORD: * Reads a Double WORD from the OBJ file. * */ DWORD GetdWord(FILE *infile, DWORD *lSize) { DWORD dWord = 0; dWord = (DWORD) GetWord(infile, lSize); // Get low order word // now get high order word, shift into upper word and or in low order word dWord |= ((DWORD) GetWord(infile, lSize) << WORDLN); return (dWord); // return complete double word } void PutByte(FILE *Outfile, TCHAR b, DWORD *plSize) { if (plSize) { (*plSize) ++; } if (fputc(b, Outfile) == EOF) { exit(-1); } } void PutWord(FILE *OutFile, WORD w, DWORD *plSize) { PutByte(OutFile, (BYTE) LOBYTE(w), plSize); PutByte(OutFile, (BYTE) HIBYTE(w), plSize); } void PutdWord (FILE *OutFile, DWORD l, DWORD *plSize) { PutWord(OutFile, LOWORD(l), plSize); PutWord(OutFile, HIWORD(l), plSize); } void PutString( FILE *OutFile, TCHAR *szStr , DWORD *plSize) { WORD i = 0; do { #ifdef RLRES16 PutByte( OutFile , szStr[ i ], plSize); #else PutWord( OutFile , szStr[ i ], plSize); #endif } while ( szStr[ i++ ] != TEXT('\0') ); } /** * Function: MyGetTempFileName * Generic funciton to create a unique file name, * using the API GetTempFileName. This * function is necessary because of the parameters * differences betweenLWIN16, and WIN32. * * * Arguments: * BYTE hDriveLetter * LPCSTR lpszPrefixString * UINT uUnique * LPSTR lpszTempFileName * * Returns: * lpszFileNameTempFileName * * * Error Codes: * 0 - invalid path returned * 1 - valid path returned * * History: * 3/92, Implemented TerryRu */ int MyGetTempFileName(BYTE hDriveLetter, LPSTR lpszPrefixString, WORD wUnique, LPSTR lpszTempFileName) { #ifdef RLWIN16 return (GetTempFileName(hDriveLetter, (LPCSTR)lpszPrefixString, (UINT)wUnique, lpszTempFileName)); #else //RLWIN16 #ifdef RLWIN32 UINT uRC; CHAR szPathName[ MAX_PATH+1]; if (! GetTempPathA((DWORD)sizeof(szPathName), (LPSTR)szPathName)) { szPathName[0] = '.'; szPathName[1] = '\0'; } uRC = GetTempFileNameA((LPSTR)szPathName, lpszPrefixString, wUnique, lpszTempFileName); return ((int)uRC); #else //RLWIN32 return (tmpnam(lpszTempFileName) == NULL ? 0 : 1); #endif // RLWIN32 #endif // RLWIN16 } /** * Function GenerateImageFile: * builds a resource from the token and rdf files * * History: * 2/92, implemented SteveBl * 7/92, modified to always use a temporary file SteveBl */ int GenerateImageFile( CHAR * szTargetImage, CHAR * szSrcImage, CHAR * szTOK, CHAR * szRDFs, WORD wFilter) { CHAR szTmpInRes[ MAXFILENAME]; CHAR szTmpOutRes[ MAXFILENAME]; CHAR szTmpTargetImage[ MAXFILENAME]; BOOL bTargetExe = FALSE; BOOL bSrcExe = FALSE; int nExeType = NOTEXE; int rc; FILE *fIn = NULL; FILE *fOut = NULL; if ( IsRes( szTOK) ) { // The given szTOK file is really a localized resource file, // place these resources into outputimage file MyGetTempFileName( 0, "TMP", 0, szTmpTargetImage); if ( IsWin32Res( szTOK) ) { rc = BuildExeFromRes32A( szTmpTargetImage, szTOK, szSrcImage); } else { rc = BuildExeFromRes16A( szTmpTargetImage, szTOK, szSrcImage); } if ( rc != 1 ) { remove( szTmpTargetImage); QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL); } if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) { remove( szTmpTargetImage); QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage); } remove( szTmpTargetImage); return ( rc); } // We're going to now do this EVERY time. Even if the target doesn't // exist. This will enable us to always work, even if we get two different // paths that resolve to the same file. MyGetTempFileName(0, "TMP", 0, szTmpTargetImage); rc = IsExe( szSrcImage); if ( rc == NTEXE || rc == WIN16EXE ) { //... resources contained in image file nExeType = rc; MyGetTempFileName( 0, "RES", 0, szTmpInRes); if ( nExeType == NTEXE ) { ExtractResFromExe32A( szSrcImage, szTmpInRes, wFilter); } else { ExtractResFromExe16A( szSrcImage, szTmpInRes, wFilter); } bSrcExe = TRUE; } else if ( rc == -1 ) { QuitA( IDS_ENGERR_01, "original source", szSrcImage); } else if ( rc == NOTEXE ) { if ( ShouldBeAnExe( szSrcImage) ) { QuitA( IDS_ENGERR_18, szSrcImage, NULL); } } else { QuitA( IDS_ENGERR_18, szSrcImage, NULL); } if ( IsRes( szTargetImage) ) { bTargetExe = FALSE; } else { bTargetExe = TRUE; } // check for valid input files if ( bSrcExe == TRUE && bTargetExe == FALSE ) { if ( nExeType == NTEXE ) { GenerateRESfromRESandTOKandRDFs( szTargetImage, szTmpInRes, szTOK, szRDFs, FALSE); return 1; } else { return -1; //... Can not generate a win16 .RES (yet) } } if ( bSrcExe == FALSE && bTargetExe == TRUE ) { // can not go from res to exe return -1; } // okay we have valid file inputs, generate image file if ( bSrcExe ) { // create name for temporary localized resource file MyGetTempFileName(0, "RES", 0, szTmpOutRes); GenerateRESfromRESandTOKandRDFs( szTmpOutRes, szTmpInRes, szTOK, szRDFs, FALSE); // now szTmpOutRes file is a localized resource file, // place these resources into outputimage file if ( nExeType == NTEXE ) { rc = BuildExeFromRes32A( szTmpTargetImage, szTmpOutRes, szSrcImage); } else { // rc = BuildExeFromRes16A( szTmpTargetImage, szTmpOutRes, szSrcImage); remove( szTmpInRes); remove( szTmpOutRes); remove( szTmpTargetImage); QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL); } // now clean up temporary files remove( szTmpInRes); remove( szTmpOutRes); if ( rc != 1 ) { remove( szTmpTargetImage); QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL); } if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) { remove( szTmpTargetImage); QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage); } remove( szTmpTargetImage); // szTargetImage is now generated, return 1; } if ( ! bSrcExe ) { // image files are resource files if ( szTmpTargetImage[0] ) { GenerateRESfromRESandTOKandRDFs( szTmpTargetImage, szSrcImage, szTOK, szRDFs, FALSE); } if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) { remove( szTmpTargetImage); QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage); } remove( szTmpTargetImage); // sztarget Image is now generated, return 1; } return 1; } /** * Function GenerateRESfromRESandTOKandRDFs: * builds a resource from the token and rdf files * * History: * 2/92, implemented SteveBl */ void GenerateRESfromRESandTOKandRDFs( CHAR * szTargetRES, //... Output exe/res file name CHAR * szSourceRES, //... Input exe/res file name CHAR * szTOK, //... Input token file name CHAR * szRDFs, //... Custom resource definition file name WORD wFilter) { FILE * fTok = NULL; FILE * fSourceRes = NULL; FILE * fTargetRes = NULL; LoadCustResDescriptions( szRDFs); if ( (fTargetRes = FOPEN( szTargetRES, "wb")) != NULL ) { if ( (fSourceRes = FOPEN( szSourceRES, "rb")) != NULL ) { if ( (fTok = FOPEN( szTOK, "rt")) != NULL ) { ReadWinRes( fSourceRes, fTargetRes, fTok, TRUE, //... Building res/exe file FALSE, //... Not building token file wFilter); FCLOSE( fTok); FCLOSE( fSourceRes); FCLOSE( fTargetRes); ClearResourceDescriptions(); } else { FCLOSE( fSourceRes); FCLOSE( fTargetRes); ClearResourceDescriptions(); QuitA( IDS_ENGERR_01, "token", szTOK); } } else { FCLOSE( fTargetRes); ClearResourceDescriptions(); QuitA( IDS_ENGERR_20, (LPSTR)IDS_INPUT, szSourceRES); } } else { ClearResourceDescriptions(); QuitA( IDS_ENGERR_20, (LPSTR)IDS_OUTPUT, szSourceRES); } } int GenerateTokFile( char *szTargetTokFile, //... Target token file, created or updated here char *szSrcImageFile, //... File from which tokens are to be made BOOL *pbTokensChanged, //... Set TRUE here if any token changes WORD wFilter) { BOOL bExeFile = FALSE; int rc = 0; FILE *fTokFile = NULL; FILE *fResFile = NULL; FILE *fTmpTokFile = NULL; FILE *fCurTokFile = NULL; FILE *fNewTokFile = NULL; static char *pchTRes = NULL; static char *pchTTok = NULL; static char *pchTMerge = NULL; *pbTokensChanged = FALSE; //... Assume nothing is changed rc = IsExe( szSrcImageFile); if ( rc == NOTEXE ) { if ( ShouldBeAnExe( szSrcImageFile) ) { QuitA( IDS_ENGERR_18, szSrcImageFile, NULL); } else { //... Src file must be a .RES file bExeFile = FALSE; pchTRes = szSrcImageFile; } } else { if ( rc == NTEXE || rc == WIN16EXE ) { //... Resources are stored in a exe file //... extract resources out of exe file into //... a temporary file. pchTRes = _tempnam( "", gszTmpPrefix); if ( rc == NTEXE ) { rc = ExtractResFromExe32A( szSrcImageFile, pchTRes, wFilter); } else { QuitA( IDS_ENGERR_19, szSrcImageFile, "16"); // rc = ExtractResFromExe16A( szSrcImageFile, // pchTRes, // wFilter); } if ( rc != 0 ) { return ( 1); } bExeFile = TRUE; } else if ( rc == -1 ) { QuitA( IDS_ENGERR_01, "source image", szSrcImageFile); } else { QuitA( IDS_ENGERR_18, szSrcImageFile, NULL); } } //... now extract tokens out of resource file //... Open res file if ( (fResFile = FOPEN( pchTRes, "rb")) == NULL ) { QuitA( IDS_ENGERR_01, bExeFile ? "temporary resource" : "resource", pchTRes); } //... Does the token file already exist? if ( NotExistsOrIsEmpty( szTargetTokFile) ) { //... No, token file does not exist. if ( (fTokFile = FOPEN( szTargetTokFile, "wt")) == NULL ) { FCLOSE( fResFile); QuitA( IDS_ENGERR_02, szTargetTokFile, NULL); } ReadWinRes( fResFile, NULL, fTokFile, FALSE, //... Not building res/exe file TRUE, //... Building token file wFilter); FCLOSE( fResFile); FCLOSE( fTokFile); } else { //... token file exists //... create a temporary file, and try to //... merge with existing one pchTTok = _tempnam( "", gszTmpPrefix); pchTMerge = _tempnam( "", gszTmpPrefix); //... open temporary file name if ( (fTmpTokFile = FOPEN( pchTTok, "wt")) == NULL ) { FCLOSE( fResFile); QuitA( IDS_ENGERR_02, pchTTok, NULL); } //... write tokens to temporary file ReadWinRes( fResFile, NULL, fTmpTokFile, FALSE, //... Not building res/exe file TRUE, //... Building token file wFilter); FCLOSE( fResFile); FCLOSE( fTmpTokFile); //... now merge temporary file with existing //... file open temporary token file if ( (fTmpTokFile = FOPEN( pchTTok, "rt")) == NULL ) { QuitA( IDS_ENGERR_01, "temporary token", pchTTok); } //... open current token file if ( (fCurTokFile = FOPEN( szTargetTokFile, "rt")) == NULL ) { FCLOSE( fTmpTokFile); QuitA( IDS_ENGERR_01, "current token", szTargetTokFile); } //... open new tok file name if ( (fNewTokFile = FOPEN( pchTMerge, "wt")) == NULL ) { FCLOSE( fTmpTokFile); FCLOSE( fCurTokFile); QuitA( IDS_ENGERR_02, pchTMerge, NULL); } //... Merge current tokens with temporary tokens *pbTokensChanged = MergeTokFiles( fNewTokFile, fCurTokFile, fTmpTokFile); FCLOSE( fNewTokFile); FCLOSE( fTmpTokFile); FCLOSE( fCurTokFile); //... bpTokensChanged, only valid if creating //... master token files so force it to be //... always true if building proj token files. if ( gbMaster == FALSE ) { *pbTokensChanged = TRUE; } if ( *pbTokensChanged ) { if ( ! CopyFileA( pchTMerge, szTargetTokFile, FALSE) ) { remove( pchTTok); remove( pchTMerge); RLFREE( pchTMerge); QuitA( IDS_COPYFILE_FAILED, pchTMerge, szTargetTokFile); } } remove( pchTTok); remove( pchTMerge); RLFREE( pchTTok); RLFREE( pchTMerge); } //... now szTargetTokFile contains latest //... tokens form szImageFile //... Clean up if we made a temp .RES file if ( bExeFile ) { rc = remove( pchTRes); RLFREE( pchTRes); } return ( 0); } BOOL ResReadBytes( FILE *InFile, //... File to read from CHAR *pBuf, //... Buffer to write to size_t dwSize, //... # bytes to read DWORD *plSize) //... bytes-read counter (or NULL) { size_t dwcRead = 0; dwcRead = fread( pBuf, 1, dwSize, InFile); if ( dwcRead == dwSize ) { if ( plSize ) { *plSize -= dwcRead; } return ( TRUE); } return ( FALSE); } int InsDlgToks( PCHAR szCurToks, PCHAR szDlgToks, WORD wFilter) { CHAR szMrgToks[MAXFILENAME]; FILE * fCurToks = NULL; FILE * fDlgToks = NULL; FILE * fMrgToks = NULL; TOKEN Tok1, Tok2; MyGetTempFileName(0,"TOK",0,szMrgToks); fMrgToks = FOPEN(szMrgToks, "w"); fCurToks = FOPEN(szCurToks, "r"); fDlgToks = FOPEN(szDlgToks, "r"); if (! (fMrgToks && fCurToks && fDlgToks)) { return -1; } while (!GetToken(fCurToks, &Tok1)) { if (Tok1.wType != wFilter) { PutToken(fMrgToks, &Tok1); RLFREE(Tok1.szText); continue; } Tok2.wType = Tok1.wType; Tok2.wName = Tok1.wName; Tok2.wID = Tok1.wID; Tok2.wFlag = Tok1.wFlag; Tok2.wLangID = Tok1.wLangID; Tok2.wReserved = 0 ; lstrcpy( Tok2.szType, Tok1.szType); lstrcpy( Tok2.szName, Tok1.szName); Tok2.szText = NULL; if (FindToken(fDlgToks, &Tok2, 0)) { Tok2.wReserved = Tok1.wReserved ; PutToken(fMrgToks, &Tok2); RLFREE(Tok2.szText); } else { PutToken(fMrgToks, &Tok1); } RLFREE(Tok1.szText); } FCLOSE (fMrgToks); FCLOSE (fCurToks); if ( ! CopyFileA( szMrgToks, szCurToks, FALSE) ) { remove( szDlgToks); remove( szMrgToks); QuitA( IDS_COPYFILE_FAILED, szMrgToks, szCurToks); } remove(szMrgToks); return 1; } //+----------------------------------------------------------------------- // // MergeTokFiles // // Returns: TRUE if a token changed, was added, or was deleted else FALSE // // History: // 7-22-92 stevebl added return value // 9-8-92 terryru changed order of translation/delta tokens // 01-25-93 MHotchin Added changes to handle var length token // text. //------------------------------------------------------------------------ BOOL MergeTokFiles( FILE *fNewTokFile, //... Final product of the merge process FILE *fCurTokFile, //... The soon-to-be-old current token file FILE *fTmpTokFile) //... The token file generated from the updated .EXE { TOKEN Tok1, Tok2; BOOL bChangesDetected = FALSE; //... Set TRUE if any token changes found BOOL bChangedText = FALSE; //... TRUE if a token's text has changed WORD cTokenCount = 0; //... Count of tokens in the new token file //... Scan through the new token file. For //... every token in the new token file, find //... the corresponding token in the current //... token file. This process will make sure //... tokens that are no longer in the .EXE //... will not be in the final token file. while ( GetToken( fTmpTokFile, &Tok1) == 0 ) { ++cTokenCount; //... Used in checking for deleted tokens bChangedText = FALSE; //... assume the token did not change //... Copy pertanent data to use in search Tok2.wType = Tok1.wType; Tok2.wName = Tok1.wName; Tok2.wID = Tok1.wID; Tok2.wFlag = Tok1.wFlag; Tok2.wLangID = Tok1.wLangID; Tok2.wReserved = 0; Tok2.szText = NULL; lstrcpy( Tok2.szType, Tok1.szType); lstrcpy( Tok2.szName, Tok1.szName); //... Now look for the corresponding token //If token is Version stamp and szTexts is "Translation", //it is 1.0 version format. So ignore it. IGNORETRANSLATION: if ( FindToken( fCurTokFile, &Tok2, 0) ) { if ( gbMaster && !(Tok2.wReserved & ST_READONLY) ) { if ( _tcscmp( (TCHAR *)Tok2.szText, (TCHAR *)Tok1.szText) ) { //... Token text changed //If the changes are only align info, translate it to the "unchanged" status. int l1, r1, t1, b1, l2, r2, t2, b2; TCHAR a1[20], a2[20]; //Cordinates token? if ( (Tok1.wType==ID_RT_DIALOG) && (Tok1.wFlag&ISCOR) //Including align info? && _stscanf(Tok1.szText,TEXT("%d %d %d %d %s"), &l1,&r1,&t1,&b1,a1) == 5 //Not including align info? && _stscanf(Tok2.szText,TEXT("%d %d %d %d %s"), &l2,&r2,&t2,&b2,a2) == 4 //Cordinates are same? && l1==l2 && r1==r2 && t1==t2 && b1==b2 ) { Tok1.wReserved = 0; } else { //If token is Version stamp and szTexts is "Translation", //it is 1.0 version format. So ignore it. if ( Tok1.wType == ID_RT_VERSION && !_tcscmp( Tok2.szText, TEXT("Translation")) ) { if ( Tok2.szText != NULL ) { RLFREE( Tok2.szText); } Tok2.szText = NULL; Tok2.wFlag = 1; goto IGNORETRANSLATION; } bChangedText = bChangesDetected = TRUE; Tok1.wReserved = ST_CHANGED|ST_NEW; Tok2.wReserved = ST_CHANGED; } } else { Tok1.wReserved = 0; } } else { Tok1.wReserved = Tok2.wReserved; } } else { //... Must be a new token (not in current token file) //If token is Version stump, and old mtk is 1.0 data file, convert it. if ( Tok1.wType==ID_RT_VERSION ) { Tok2.szText = NULL; Tok2.wFlag = 1; _tcscpy( Tok2.szName, TEXT("VALUE") ); if ( FindToken( fCurTokFile, &Tok2, 0) && ! lstrcmp( Tok1.szText, Tok2.szText) ) { Tok1.wReserved = Tok2.wReserved; } else Tok1.wReserved = ST_TRANSLATED | ST_DIRTY; } else { Tok1.wReserved = ST_TRANSLATED | ST_DIRTY; } bChangesDetected = TRUE; } //... Copy token from new token file to final token //... file. If a change was detected, then copy the //... original token (from the "current" token file //... into the final token file. PutToken( fNewTokFile, &Tok1); RLFREE( Tok1.szText); if ( bChangedText ) { PutToken( fNewTokFile, &Tok2); // now delta tokens follow translation tokens } if ( Tok2.szText != NULL ) { RLFREE( Tok2.szText); } } if ( ! bChangesDetected ) { // We have to test to be sure that no tokens were deleted // since we know that none changed. rewind( fCurTokFile); //... Look for tokens that exist in the current //... token file that do not exist in the token //... file created from the updated .EXE. while ( GetToken( fCurTokFile, &Tok1) == 0 ) { --cTokenCount; RLFREE( Tok1.szText); } if ( cTokenCount != 0 ) { bChangesDetected = TRUE; } } return ( bChangesDetected); } void MakeNewExt(char *NewName, char *OldName, char *ext) { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; // dummy vars to hold file name info char dext[_MAX_EXT]; // Split obj file name into filename and extention _splitpath(OldName, drive, dir, fname, dext); // Make new file name with new ext extention _makepath(NewName, drive, dir, fname, ext); } //...................................................................... //... //... Check to see if the given file name *should* be an EXE //... //... Return: TRUE if it should, else FALSE. static BOOL ShouldBeAnExe( PCHAR szFileName) { PCHAR psz; if ( (psz = strrchr( szFileName, '.')) != NULL ) { if ( IsRes( szFileName) ) { return ( FALSE); } else if ( lstrcmpiA( psz, ".exe") == 0 || lstrcmpiA( psz, ".dll") == 0 || lstrcmpiA( psz, ".com") == 0 || lstrcmpiA( psz, ".scr") == 0 || lstrcmpiA( psz, ".cpl") == 0 ) { return ( TRUE); } //... Because we think this case of filename //... would be not executable file rather than res file. else if ( lstrcmpiA( psz, ".tmp") == 0 ) { //for tmp file created by Dlgedit return ( FALSE ); } else { return ( TRUE ); } } return ( FALSE); } //......................................................... //... //... If the named file exists and is not empty, return FALSE, else TRUE. static BOOL NotExistsOrIsEmpty( PCHAR pszFileName) { BOOL fRC = TRUE; int hFile = -1; //... Does file not exist? if ( _access( pszFileName, 0) == 0 ) { //... No, file exists. Open it. if ( (hFile = _open( pszFileName, _O_RDONLY)) != -1 ) { //... Is it Empty? if ( _filelength( hFile) == 0L ) { fRC = TRUE; //... Yes, file is empty. } else { fRC = FALSE; //... No, file is not empty. } _close( hFile); } else { QuitA( IDS_ENGERR_01, "non-empty", pszFileName); } } else { fRC = TRUE; //... Yes, file does not exist. } return ( fRC); }