Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1273 lines
34 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <io.h>
  4. #include <string.h>
  5. //#include <malloc.h>
  6. #include <tchar.h>
  7. //#include <assert.h>
  8. //#include <sys\types.h>
  9. //#include <sys\stat.h>
  10. #include <fcntl.h>
  11. #ifdef RLDOS
  12. #include "dosdefs.h"
  13. #else //RLDOS
  14. #include <windows.h>
  15. #include "windefs.h"
  16. #endif //RLDOS
  17. #include "resread.h"
  18. #include "restok.h"
  19. #include "custres.h"
  20. #ifdef RLRES32
  21. #include "exentres.h"
  22. #include "reswin16.h"
  23. #else //RLRES32
  24. #include "exe2res.h"
  25. #endif //RLRES32
  26. UCHAR szDHW[ DHWSIZE]; //... Common temporary buffer
  27. char * gszTmpPrefix = "$RLT"; //... Temporary name prefix
  28. BOOL gbMaster = FALSE; //... TRUE if Working in Master project
  29. BOOL gfReplace = TRUE; //... FALSE if appending new language to exe
  30. BOOL gbShowWarnings = FALSE; //... Display warnining messages if TRUE
  31. #ifdef _DEBUG
  32. PMEMLIST pMemList = NULL;
  33. #endif
  34. static BOOL ShouldBeAnExe( CHAR *);
  35. static BOOL NotExistsOrIsEmpty( PCHAR szTargetTokFile);
  36. /**
  37. *
  38. *
  39. * Function: DWORDfpUP
  40. * Move the file pointer to the next 32 bit boundary.
  41. *
  42. *
  43. * Arguments:
  44. * Infile: File pointer to seek
  45. * plSize: Address of Resource size var
  46. *
  47. * Returns:
  48. * Number of padding to next 32 bit boundary, and addjusts resource size var
  49. *
  50. * Errors Codes:
  51. * -1, fseek failed
  52. *
  53. * History:
  54. * 10/11/91 Implemented TerryRu
  55. *
  56. *
  57. **/
  58. DWORD DWORDfpUP(FILE * InFile, DWORD *plSize)
  59. {
  60. DWORD tPos;
  61. DWORD Align;
  62. tPos = (ftell(InFile));
  63. Align = DWORDUP(tPos);
  64. *plSize -= (Align - tPos);
  65. fseek( InFile, Align, SEEK_SET);
  66. return ( Align - tPos);
  67. }
  68. /*
  69. *
  70. * Function GetName,
  71. * Copies a name from the OBJ file into the ObjInfo Structure.
  72. *
  73. */
  74. void GetName( FILE *infile, TCHAR *szName , DWORD *lSize)
  75. {
  76. WORD i = 0;
  77. do {
  78. #ifdef RLRES16
  79. szName[ i ] = GetByte( infile, lSize);
  80. #else
  81. szName[ i ] = GetWord( infile, lSize);
  82. #endif
  83. } while ( szName[ i++ ] != TEXT('\0') );
  84. }
  85. /*
  86. *
  87. * Function MyAlloc:
  88. * Memory allocation routine with error checking.
  89. *
  90. */
  91. #ifdef _DEBUG
  92. PBYTE MyAlloc( DWORD dwSize, LPSTR pszFile, WORD wLine)
  93. #else
  94. PBYTE MyAlloc( DWORD dwSize)
  95. #endif
  96. {
  97. PBYTE ptr = NULL;
  98. HGLOBAL hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT,
  99. (size_t)((dwSize > 0) ? dwSize : sizeof( TCHAR)));
  100. if ( hMem == NULL ) {
  101. QuitT( IDS_ENGERR_11, NULL, NULL);
  102. } else {
  103. ptr = GlobalLock( hMem);
  104. }
  105. #ifdef _DEBUG
  106. {
  107. PMEMLIST pTmpMem = (PMEMLIST)GlobalAlloc( GPTR, sizeof( MEMLIST));
  108. pTmpMem->pNext = pMemList;
  109. pMemList = pTmpMem;
  110. lstrcpyA( pMemList->szMemFile, pszFile);
  111. pMemList->wMemLine = wLine;
  112. pMemList->pMem = ptr;
  113. }
  114. #endif // _DEBUG
  115. return ( ptr); // memory allocation okay.
  116. }
  117. //..........................................................................
  118. //ppc cause access violation
  119. void MyFree( void *UNALIGNED*p)
  120. {
  121. if ( p && *p ) {
  122. #ifdef _DEBUG
  123. FreeMemListItem( *p, NULL);
  124. #else
  125. HGLOBAL hMem = GlobalHandle( (HANDLE)*p);
  126. GlobalUnlock( hMem);
  127. GlobalFree( hMem);
  128. #endif // _DEBUG
  129. *p = NULL;
  130. }
  131. }
  132. #ifdef _DEBUG
  133. void FreeMemList( FILE *pfMemFile)
  134. {
  135. while ( pMemList ) {
  136. FreeMemListItem( pMemList->pMem, pfMemFile);
  137. }
  138. }
  139. void FreeMemListItem( void *p, FILE *pfMemFile)
  140. {
  141. if ( pMemList && p ) {
  142. PMEMLIST pThisMem = NULL;
  143. PMEMLIST pNextMem = NULL;
  144. PMEMLIST pPrevMem = NULL;
  145. for ( pThisMem = pMemList; pThisMem; pThisMem = pNextMem ) {
  146. pNextMem = pThisMem->pNext;
  147. if ( pThisMem->pMem == p ) {
  148. HGLOBAL hMem = NULL;
  149. if ( pfMemFile ) {
  150. fprintf( pfMemFile,
  151. "%u\t%s\n",
  152. pThisMem->wMemLine,
  153. pThisMem->szMemFile);
  154. }
  155. hMem = GlobalHandle( p);
  156. GlobalUnlock( hMem);
  157. GlobalFree( hMem);
  158. GlobalFree( pThisMem);
  159. if ( pPrevMem ) {
  160. pPrevMem->pNext = pNextMem;
  161. } else {
  162. pMemList = pNextMem;
  163. }
  164. break;
  165. }
  166. pPrevMem = pThisMem;
  167. }
  168. }
  169. }
  170. #endif // _DEBUG
  171. /*
  172. *
  173. * Function MyReAlloc
  174. *
  175. * Re-allocate memory with error checking.
  176. *
  177. * History:
  178. * 01/21/93 MHotchin Implemented.
  179. *
  180. */
  181. #ifdef _DEBUG
  182. PBYTE MyReAlloc(
  183. PBYTE pOldMem, //... Current ptr to buffer
  184. DWORD cSize, //... New size for buffer
  185. LPSTR pszFile,
  186. WORD wLine)
  187. #else
  188. PBYTE MyReAlloc(
  189. PBYTE pOldMem, //... Current ptr to buffer
  190. DWORD cSize) //... New size for buffer
  191. #endif // _DEBUG
  192. {
  193. PBYTE ptr = NULL;
  194. HGLOBAL hMem = NULL;
  195. hMem = GlobalHandle( pOldMem);
  196. if ( hMem == NULL ) {
  197. QuitT( IDS_ENGERR_11, NULL, NULL);
  198. }
  199. if ( GlobalUnlock( hMem) || GetLastError() != NO_ERROR ) {
  200. QuitT( IDS_ENGERR_11, NULL, NULL);
  201. }
  202. hMem = GlobalReAlloc( hMem, cSize, GMEM_MOVEABLE | GMEM_ZEROINIT);
  203. if ( hMem == NULL ) {
  204. QuitT( IDS_ENGERR_11, NULL, NULL);
  205. }
  206. ptr = GlobalLock( hMem);
  207. #ifdef _DEBUG
  208. if ( ptr != pOldMem ) {
  209. PMEMLIST pThisMem = NULL;
  210. PMEMLIST pNextMem = NULL;
  211. for ( pThisMem = pMemList; pThisMem; pThisMem = pThisMem->pNext ) {
  212. if ( pThisMem->pMem == pOldMem ) {
  213. pThisMem->pMem = ptr;
  214. break;
  215. }
  216. }
  217. }
  218. #endif // _DEBUG
  219. return ( ptr);
  220. }
  221. /*
  222. *
  223. * Function GetByte:
  224. * Reads a byte from the input file stream, and checks for EOF.
  225. *
  226. */
  227. BYTE GetByte(FILE *pInFile, DWORD *pdwSize)
  228. {
  229. register int n;
  230. if ( pdwSize ) {
  231. (*pdwSize)--;
  232. }
  233. n = fgetc( pInFile);
  234. if ( n == EOF ) {
  235. if ( feof( pInFile) ) {
  236. exit(-1);
  237. }
  238. }
  239. return ( (BYTE)n);
  240. }
  241. /*
  242. *
  243. * Function UnGetByte:
  244. *
  245. * Returns the character C into the input stream, and updates the Record Length.
  246. *
  247. * Calls:
  248. * ungetc, To return character
  249. * DiffObjExit, If unable to insert the character into the input stream
  250. *
  251. * Caller:
  252. * GetFixUpP,
  253. *
  254. */
  255. void UnGetByte(FILE *infile, BYTE c, DWORD *lSize)
  256. {
  257. if (lSize) {
  258. (*lSize)++;
  259. }
  260. if (ungetc(c, infile)== EOF) {
  261. exit (-1);
  262. }
  263. // c put back into input stream
  264. }
  265. /*
  266. *
  267. * Function UnGetWord:
  268. *
  269. * Returns the word C into the input stream, and updates the Record Length.
  270. *
  271. * Calls:
  272. *
  273. * Caller:
  274. *
  275. */
  276. void UnGetWord(FILE *infile, WORD c, DWORD *lSize)
  277. {
  278. long lCurrentOffset;
  279. if (lSize) {
  280. (*lSize) += 2;
  281. }
  282. lCurrentOffset = ftell(infile);
  283. if (fseek(infile, (lCurrentOffset - 2L) , SEEK_SET)) {
  284. exit (-1);
  285. }
  286. }
  287. /*
  288. *
  289. * Function SkipBytes:
  290. * Reads and ignores n bytes from the input stream
  291. *
  292. */
  293. void SkipBytes(FILE *infile, DWORD *pcBytes)
  294. {
  295. if (fseek(infile, (DWORD) *pcBytes, SEEK_CUR) == -1L) {
  296. exit (-1);
  297. }
  298. *pcBytes=0;
  299. }
  300. /*
  301. * Function GetWord:
  302. * Reads a WORD from the RES file.
  303. *
  304. */
  305. WORD GetWord(FILE *infile, DWORD *lSize)
  306. {
  307. // Get low order byte
  308. register WORD lobyte;
  309. lobyte = GetByte(infile, lSize);
  310. return (lobyte + (GetByte(infile, lSize) << BYTELN));
  311. }
  312. /*
  313. *
  314. * Function GetDWORD:
  315. * Reads a Double WORD from the OBJ file.
  316. *
  317. */
  318. DWORD GetdWord(FILE *infile, DWORD *lSize)
  319. {
  320. DWORD dWord = 0;
  321. dWord = (DWORD) GetWord(infile, lSize);
  322. // Get low order word
  323. // now get high order word, shift into upper word and or in low order word
  324. dWord |= ((DWORD) GetWord(infile, lSize) << WORDLN);
  325. return (dWord);
  326. // return complete double word
  327. }
  328. void PutByte(FILE *Outfile, TCHAR b, DWORD *plSize)
  329. {
  330. if (plSize) {
  331. (*plSize) ++;
  332. }
  333. if (fputc(b, Outfile) == EOF) {
  334. exit(-1);
  335. }
  336. }
  337. void PutWord(FILE *OutFile, WORD w, DWORD *plSize)
  338. {
  339. PutByte(OutFile, (BYTE) LOBYTE(w), plSize);
  340. PutByte(OutFile, (BYTE) HIBYTE(w), plSize);
  341. }
  342. void PutdWord (FILE *OutFile, DWORD l, DWORD *plSize)
  343. {
  344. PutWord(OutFile, LOWORD(l), plSize);
  345. PutWord(OutFile, HIWORD(l), plSize);
  346. }
  347. void PutString( FILE *OutFile, TCHAR *szStr , DWORD *plSize)
  348. {
  349. WORD i = 0;
  350. do {
  351. #ifdef RLRES16
  352. PutByte( OutFile , szStr[ i ], plSize);
  353. #else
  354. PutWord( OutFile , szStr[ i ], plSize);
  355. #endif
  356. } while ( szStr[ i++ ] != TEXT('\0') );
  357. }
  358. /**
  359. * Function: MyGetTempFileName
  360. * Generic funciton to create a unique file name,
  361. * using the API GetTempFileName. This
  362. * function is necessary because of the parameters
  363. * differences betweenLWIN16, and WIN32.
  364. *
  365. *
  366. * Arguments:
  367. * BYTE hDriveLetter
  368. * LPCSTR lpszPrefixString
  369. * UINT uUnique
  370. * LPSTR lpszTempFileName
  371. *
  372. * Returns:
  373. * lpszFileNameTempFileName
  374. *
  375. *
  376. * Error Codes:
  377. * 0 - invalid path returned
  378. * 1 - valid path returned
  379. *
  380. * History:
  381. * 3/92, Implemented TerryRu
  382. */
  383. int MyGetTempFileName(BYTE hDriveLetter,
  384. LPSTR lpszPrefixString,
  385. WORD wUnique,
  386. LPSTR lpszTempFileName)
  387. {
  388. #ifdef RLWIN16
  389. return (GetTempFileName(hDriveLetter,
  390. (LPCSTR)lpszPrefixString,
  391. (UINT)wUnique,
  392. lpszTempFileName));
  393. #else //RLWIN16
  394. #ifdef RLWIN32
  395. UINT uRC;
  396. CHAR szPathName[ MAX_PATH+1];
  397. if (! GetTempPathA((DWORD)sizeof(szPathName), (LPSTR)szPathName)) {
  398. szPathName[0] = '.';
  399. szPathName[1] = '\0';
  400. }
  401. uRC = GetTempFileNameA((LPSTR)szPathName,
  402. lpszPrefixString,
  403. wUnique,
  404. lpszTempFileName);
  405. return ((int)uRC);
  406. #else //RLWIN32
  407. return (tmpnam(lpszTempFileName) == NULL ? 0 : 1);
  408. #endif // RLWIN32
  409. #endif // RLWIN16
  410. }
  411. /**
  412. * Function GenerateImageFile:
  413. * builds a resource from the token and rdf files
  414. *
  415. * History:
  416. * 2/92, implemented SteveBl
  417. * 7/92, modified to always use a temporary file SteveBl
  418. */
  419. int GenerateImageFile(
  420. CHAR * szTargetImage,
  421. CHAR * szSrcImage,
  422. CHAR * szTOK,
  423. CHAR * szRDFs,
  424. WORD wFilter)
  425. {
  426. CHAR szTmpInRes[ MAXFILENAME];
  427. CHAR szTmpOutRes[ MAXFILENAME];
  428. CHAR szTmpTargetImage[ MAXFILENAME];
  429. BOOL bTargetExe = FALSE;
  430. BOOL bSrcExe = FALSE;
  431. int nExeType = NOTEXE;
  432. int rc;
  433. FILE *fIn = NULL;
  434. FILE *fOut = NULL;
  435. if ( IsRes( szTOK) ) {
  436. // The given szTOK file is really a localized resource file,
  437. // place these resources into outputimage file
  438. MyGetTempFileName( 0, "TMP", 0, szTmpTargetImage);
  439. if ( IsWin32Res( szTOK) ) {
  440. rc = BuildExeFromRes32A( szTmpTargetImage, szTOK, szSrcImage);
  441. } else {
  442. rc = BuildExeFromRes16A( szTmpTargetImage, szTOK, szSrcImage);
  443. }
  444. if ( rc != 1 ) {
  445. remove( szTmpTargetImage);
  446. QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL);
  447. }
  448. if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) {
  449. remove( szTmpTargetImage);
  450. QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage);
  451. }
  452. remove( szTmpTargetImage);
  453. return ( rc);
  454. }
  455. // We're going to now do this EVERY time. Even if the target doesn't
  456. // exist. This will enable us to always work, even if we get two different
  457. // paths that resolve to the same file.
  458. MyGetTempFileName(0, "TMP", 0, szTmpTargetImage);
  459. rc = IsExe( szSrcImage);
  460. if ( rc == NTEXE || rc == WIN16EXE ) {
  461. //... resources contained in image file
  462. nExeType = rc;
  463. MyGetTempFileName( 0, "RES", 0, szTmpInRes);
  464. if ( nExeType == NTEXE ) {
  465. ExtractResFromExe32A( szSrcImage, szTmpInRes, wFilter);
  466. } else {
  467. ExtractResFromExe16A( szSrcImage, szTmpInRes, wFilter);
  468. }
  469. bSrcExe = TRUE;
  470. } else if ( rc == -1 ) {
  471. QuitA( IDS_ENGERR_01, "original source", szSrcImage);
  472. } else if ( rc == NOTEXE ) {
  473. if ( ShouldBeAnExe( szSrcImage) ) {
  474. QuitA( IDS_ENGERR_18, szSrcImage, NULL);
  475. }
  476. } else {
  477. QuitA( IDS_ENGERR_18, szSrcImage, NULL);
  478. }
  479. if ( IsRes( szTargetImage) ) {
  480. bTargetExe = FALSE;
  481. } else {
  482. bTargetExe = TRUE;
  483. }
  484. // check for valid input files
  485. if ( bSrcExe == TRUE && bTargetExe == FALSE ) {
  486. if ( nExeType == NTEXE ) {
  487. GenerateRESfromRESandTOKandRDFs( szTargetImage,
  488. szTmpInRes,
  489. szTOK,
  490. szRDFs,
  491. FALSE);
  492. return 1;
  493. } else {
  494. return -1; //... Can not generate a win16 .RES (yet)
  495. }
  496. }
  497. if ( bSrcExe == FALSE && bTargetExe == TRUE ) {
  498. // can not go from res to exe
  499. return -1;
  500. }
  501. // okay we have valid file inputs, generate image file
  502. if ( bSrcExe ) {
  503. // create name for temporary localized resource file
  504. MyGetTempFileName(0, "RES", 0, szTmpOutRes);
  505. GenerateRESfromRESandTOKandRDFs( szTmpOutRes,
  506. szTmpInRes,
  507. szTOK,
  508. szRDFs,
  509. FALSE);
  510. // now szTmpOutRes file is a localized resource file,
  511. // place these resources into outputimage file
  512. if ( nExeType == NTEXE ) {
  513. rc = BuildExeFromRes32A( szTmpTargetImage, szTmpOutRes, szSrcImage);
  514. } else {
  515. // rc = BuildExeFromRes16A( szTmpTargetImage, szTmpOutRes, szSrcImage);
  516. remove( szTmpInRes);
  517. remove( szTmpOutRes);
  518. remove( szTmpTargetImage);
  519. QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL);
  520. }
  521. // now clean up temporary files
  522. remove( szTmpInRes);
  523. remove( szTmpOutRes);
  524. if ( rc != 1 ) {
  525. remove( szTmpTargetImage);
  526. QuitT( IDS_ENGERR_16, (LPTSTR)IDS_NOBLDEXERES, NULL);
  527. }
  528. if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) {
  529. remove( szTmpTargetImage);
  530. QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage);
  531. }
  532. remove( szTmpTargetImage);
  533. // szTargetImage is now generated,
  534. return 1;
  535. }
  536. if ( ! bSrcExe ) {
  537. // image files are resource files
  538. if ( szTmpTargetImage[0] ) {
  539. GenerateRESfromRESandTOKandRDFs( szTmpTargetImage,
  540. szSrcImage,
  541. szTOK,
  542. szRDFs,
  543. FALSE);
  544. }
  545. if ( ! CopyFileA( szTmpTargetImage, szTargetImage, FALSE) ) {
  546. remove( szTmpTargetImage);
  547. QuitA( IDS_COPYFILE_FAILED, szTmpTargetImage, szTargetImage);
  548. }
  549. remove( szTmpTargetImage);
  550. // sztarget Image is now generated,
  551. return 1;
  552. }
  553. return 1;
  554. }
  555. /**
  556. * Function GenerateRESfromRESandTOKandRDFs:
  557. * builds a resource from the token and rdf files
  558. *
  559. * History:
  560. * 2/92, implemented SteveBl
  561. */
  562. void GenerateRESfromRESandTOKandRDFs(
  563. CHAR * szTargetRES, //... Output exe/res file name
  564. CHAR * szSourceRES, //... Input exe/res file name
  565. CHAR * szTOK, //... Input token file name
  566. CHAR * szRDFs, //... Custom resource definition file name
  567. WORD wFilter)
  568. {
  569. FILE * fTok = NULL;
  570. FILE * fSourceRes = NULL;
  571. FILE * fTargetRes = NULL;
  572. LoadCustResDescriptions( szRDFs);
  573. if ( (fTargetRes = FOPEN( szTargetRES, "wb")) != NULL ) {
  574. if ( (fSourceRes = FOPEN( szSourceRES, "rb")) != NULL ) {
  575. if ( (fTok = FOPEN( szTOK, "rt")) != NULL ) {
  576. ReadWinRes( fSourceRes,
  577. fTargetRes,
  578. fTok,
  579. TRUE, //... Building res/exe file
  580. FALSE, //... Not building token file
  581. wFilter);
  582. FCLOSE( fTok);
  583. FCLOSE( fSourceRes);
  584. FCLOSE( fTargetRes);
  585. ClearResourceDescriptions();
  586. } else {
  587. FCLOSE( fSourceRes);
  588. FCLOSE( fTargetRes);
  589. ClearResourceDescriptions();
  590. QuitA( IDS_ENGERR_01, "token", szTOK);
  591. }
  592. } else {
  593. FCLOSE( fTargetRes);
  594. ClearResourceDescriptions();
  595. QuitA( IDS_ENGERR_20, (LPSTR)IDS_INPUT, szSourceRES);
  596. }
  597. } else {
  598. ClearResourceDescriptions();
  599. QuitA( IDS_ENGERR_20, (LPSTR)IDS_OUTPUT, szSourceRES);
  600. }
  601. }
  602. int GenerateTokFile(
  603. char *szTargetTokFile, //... Target token file, created or updated here
  604. char *szSrcImageFile, //... File from which tokens are to be made
  605. BOOL *pbTokensChanged, //... Set TRUE here if any token changes
  606. WORD wFilter)
  607. {
  608. BOOL bExeFile = FALSE;
  609. int rc = 0;
  610. FILE *fTokFile = NULL;
  611. FILE *fResFile = NULL;
  612. FILE *fTmpTokFile = NULL;
  613. FILE *fCurTokFile = NULL;
  614. FILE *fNewTokFile = NULL;
  615. static char *pchTRes = NULL;
  616. static char *pchTTok = NULL;
  617. static char *pchTMerge = NULL;
  618. *pbTokensChanged = FALSE; //... Assume nothing is changed
  619. rc = IsExe( szSrcImageFile);
  620. if ( rc == NOTEXE ) {
  621. if ( ShouldBeAnExe( szSrcImageFile) ) {
  622. QuitA( IDS_ENGERR_18, szSrcImageFile, NULL);
  623. } else { //... Src file must be a .RES file
  624. bExeFile = FALSE;
  625. pchTRes = szSrcImageFile;
  626. }
  627. } else {
  628. if ( rc == NTEXE || rc == WIN16EXE ) {
  629. //... Resources are stored in a exe file
  630. //... extract resources out of exe file into
  631. //... a temporary file.
  632. pchTRes = _tempnam( "", gszTmpPrefix);
  633. if ( rc == NTEXE ) {
  634. rc = ExtractResFromExe32A( szSrcImageFile,
  635. pchTRes,
  636. wFilter);
  637. } else {
  638. QuitA( IDS_ENGERR_19, szSrcImageFile, "16");
  639. // rc = ExtractResFromExe16A( szSrcImageFile,
  640. // pchTRes,
  641. // wFilter);
  642. }
  643. if ( rc != 0 ) {
  644. return ( 1);
  645. }
  646. bExeFile = TRUE;
  647. } else if ( rc == -1 ) {
  648. QuitA( IDS_ENGERR_01, "source image", szSrcImageFile);
  649. } else {
  650. QuitA( IDS_ENGERR_18, szSrcImageFile, NULL);
  651. }
  652. }
  653. //... now extract tokens out of resource file
  654. //... Open res file
  655. if ( (fResFile = FOPEN( pchTRes, "rb")) == NULL ) {
  656. QuitA( IDS_ENGERR_01,
  657. bExeFile ? "temporary resource" : "resource",
  658. pchTRes);
  659. }
  660. //... Does the token file already exist?
  661. if ( NotExistsOrIsEmpty( szTargetTokFile) ) {
  662. //... No, token file does not exist.
  663. if ( (fTokFile = FOPEN( szTargetTokFile, "wt")) == NULL ) {
  664. FCLOSE( fResFile);
  665. QuitA( IDS_ENGERR_02, szTargetTokFile, NULL);
  666. }
  667. ReadWinRes( fResFile,
  668. NULL,
  669. fTokFile,
  670. FALSE, //... Not building res/exe file
  671. TRUE, //... Building token file
  672. wFilter);
  673. FCLOSE( fResFile);
  674. FCLOSE( fTokFile);
  675. } else {
  676. //... token file exists
  677. //... create a temporary file, and try to
  678. //... merge with existing one
  679. pchTTok = _tempnam( "", gszTmpPrefix);
  680. pchTMerge = _tempnam( "", gszTmpPrefix);
  681. //... open temporary file name
  682. if ( (fTmpTokFile = FOPEN( pchTTok, "wt")) == NULL ) {
  683. FCLOSE( fResFile);
  684. QuitA( IDS_ENGERR_02, pchTTok, NULL);
  685. }
  686. //... write tokens to temporary file
  687. ReadWinRes( fResFile,
  688. NULL,
  689. fTmpTokFile,
  690. FALSE, //... Not building res/exe file
  691. TRUE, //... Building token file
  692. wFilter);
  693. FCLOSE( fResFile);
  694. FCLOSE( fTmpTokFile);
  695. //... now merge temporary file with existing
  696. //... file open temporary token file
  697. if ( (fTmpTokFile = FOPEN( pchTTok, "rt")) == NULL ) {
  698. QuitA( IDS_ENGERR_01, "temporary token", pchTTok);
  699. }
  700. //... open current token file
  701. if ( (fCurTokFile = FOPEN( szTargetTokFile, "rt")) == NULL ) {
  702. FCLOSE( fTmpTokFile);
  703. QuitA( IDS_ENGERR_01, "current token", szTargetTokFile);
  704. }
  705. //... open new tok file name
  706. if ( (fNewTokFile = FOPEN( pchTMerge, "wt")) == NULL ) {
  707. FCLOSE( fTmpTokFile);
  708. FCLOSE( fCurTokFile);
  709. QuitA( IDS_ENGERR_02, pchTMerge, NULL);
  710. }
  711. //... Merge current tokens with temporary tokens
  712. *pbTokensChanged = MergeTokFiles( fNewTokFile,
  713. fCurTokFile,
  714. fTmpTokFile);
  715. FCLOSE( fNewTokFile);
  716. FCLOSE( fTmpTokFile);
  717. FCLOSE( fCurTokFile);
  718. //... bpTokensChanged, only valid if creating
  719. //... master token files so force it to be
  720. //... always true if building proj token files.
  721. if ( gbMaster == FALSE ) {
  722. *pbTokensChanged = TRUE;
  723. }
  724. if ( *pbTokensChanged ) {
  725. if ( ! CopyFileA( pchTMerge, szTargetTokFile, FALSE) ) {
  726. remove( pchTTok);
  727. remove( pchTMerge);
  728. RLFREE( pchTMerge);
  729. QuitA( IDS_COPYFILE_FAILED, pchTMerge, szTargetTokFile);
  730. }
  731. }
  732. remove( pchTTok);
  733. remove( pchTMerge);
  734. RLFREE( pchTTok);
  735. RLFREE( pchTMerge);
  736. }
  737. //... now szTargetTokFile contains latest
  738. //... tokens form szImageFile
  739. //... Clean up if we made a temp .RES file
  740. if ( bExeFile ) {
  741. rc = remove( pchTRes);
  742. RLFREE( pchTRes);
  743. }
  744. return ( 0);
  745. }
  746. BOOL ResReadBytes(
  747. FILE *InFile, //... File to read from
  748. CHAR *pBuf, //... Buffer to write to
  749. size_t dwSize, //... # bytes to read
  750. DWORD *plSize) //... bytes-read counter (or NULL)
  751. {
  752. size_t dwcRead = 0;
  753. dwcRead = fread( pBuf, 1, dwSize, InFile);
  754. if ( dwcRead == dwSize ) {
  755. if ( plSize ) {
  756. *plSize -= dwcRead;
  757. }
  758. return ( TRUE);
  759. }
  760. return ( FALSE);
  761. }
  762. int InsDlgToks( PCHAR szCurToks, PCHAR szDlgToks, WORD wFilter)
  763. {
  764. CHAR szMrgToks[MAXFILENAME];
  765. FILE * fCurToks = NULL;
  766. FILE * fDlgToks = NULL;
  767. FILE * fMrgToks = NULL;
  768. TOKEN Tok1, Tok2;
  769. MyGetTempFileName(0,"TOK",0,szMrgToks);
  770. fMrgToks = FOPEN(szMrgToks, "w");
  771. fCurToks = FOPEN(szCurToks, "r");
  772. fDlgToks = FOPEN(szDlgToks, "r");
  773. if (! (fMrgToks && fCurToks && fDlgToks)) {
  774. return -1;
  775. }
  776. while (!GetToken(fCurToks, &Tok1)) {
  777. if (Tok1.wType != wFilter) {
  778. PutToken(fMrgToks, &Tok1);
  779. RLFREE(Tok1.szText);
  780. continue;
  781. }
  782. Tok2.wType = Tok1.wType;
  783. Tok2.wName = Tok1.wName;
  784. Tok2.wID = Tok1.wID;
  785. Tok2.wFlag = Tok1.wFlag;
  786. Tok2.wLangID = Tok1.wLangID;
  787. Tok2.wReserved = 0 ;
  788. lstrcpy( Tok2.szType, Tok1.szType);
  789. lstrcpy( Tok2.szName, Tok1.szName);
  790. Tok2.szText = NULL;
  791. if (FindToken(fDlgToks, &Tok2, 0)) {
  792. Tok2.wReserved = Tok1.wReserved ;
  793. PutToken(fMrgToks, &Tok2);
  794. RLFREE(Tok2.szText);
  795. } else {
  796. PutToken(fMrgToks, &Tok1);
  797. }
  798. RLFREE(Tok1.szText);
  799. }
  800. FCLOSE (fMrgToks);
  801. FCLOSE (fCurToks);
  802. if ( ! CopyFileA( szMrgToks, szCurToks, FALSE) ) {
  803. remove( szDlgToks);
  804. remove( szMrgToks);
  805. QuitA( IDS_COPYFILE_FAILED, szMrgToks, szCurToks);
  806. }
  807. remove(szMrgToks);
  808. return 1;
  809. }
  810. //+-----------------------------------------------------------------------
  811. //
  812. // MergeTokFiles
  813. //
  814. // Returns: TRUE if a token changed, was added, or was deleted else FALSE
  815. //
  816. // History:
  817. // 7-22-92 stevebl added return value
  818. // 9-8-92 terryru changed order of translation/delta tokens
  819. // 01-25-93 MHotchin Added changes to handle var length token
  820. // text.
  821. //------------------------------------------------------------------------
  822. BOOL MergeTokFiles(
  823. FILE *fNewTokFile, //... Final product of the merge process
  824. FILE *fCurTokFile, //... The soon-to-be-old current token file
  825. FILE *fTmpTokFile) //... The token file generated from the updated .EXE
  826. {
  827. TOKEN Tok1, Tok2;
  828. BOOL bChangesDetected = FALSE; //... Set TRUE if any token changes found
  829. BOOL bChangedText = FALSE; //... TRUE if a token's text has changed
  830. WORD cTokenCount = 0; //... Count of tokens in the new token file
  831. //... Scan through the new token file. For
  832. //... every token in the new token file, find
  833. //... the corresponding token in the current
  834. //... token file. This process will make sure
  835. //... tokens that are no longer in the .EXE
  836. //... will not be in the final token file.
  837. while ( GetToken( fTmpTokFile, &Tok1) == 0 ) {
  838. ++cTokenCount; //... Used in checking for deleted tokens
  839. bChangedText = FALSE; //... assume the token did not change
  840. //... Copy pertanent data to use in search
  841. Tok2.wType = Tok1.wType;
  842. Tok2.wName = Tok1.wName;
  843. Tok2.wID = Tok1.wID;
  844. Tok2.wFlag = Tok1.wFlag;
  845. Tok2.wLangID = Tok1.wLangID;
  846. Tok2.wReserved = 0;
  847. Tok2.szText = NULL;
  848. lstrcpy( Tok2.szType, Tok1.szType);
  849. lstrcpy( Tok2.szName, Tok1.szName);
  850. //... Now look for the corresponding token
  851. //If token is Version stamp and szTexts is "Translation",
  852. //it is 1.0 version format. So ignore it.
  853. IGNORETRANSLATION:
  854. if ( FindToken( fCurTokFile, &Tok2, 0) ) {
  855. if ( gbMaster && !(Tok2.wReserved & ST_READONLY) ) {
  856. if ( _tcscmp( (TCHAR *)Tok2.szText, (TCHAR *)Tok1.szText) ) {
  857. //... Token text changed
  858. //If the changes are only align info, translate it to the "unchanged" status.
  859. int l1, r1, t1, b1, l2, r2, t2, b2;
  860. TCHAR a1[20], a2[20];
  861. //Cordinates token?
  862. if ( (Tok1.wType==ID_RT_DIALOG) && (Tok1.wFlag&ISCOR)
  863. //Including align info?
  864. && _stscanf(Tok1.szText,TEXT("%d %d %d %d %s"),
  865. &l1,&r1,&t1,&b1,a1) == 5
  866. //Not including align info?
  867. && _stscanf(Tok2.szText,TEXT("%d %d %d %d %s"),
  868. &l2,&r2,&t2,&b2,a2) == 4
  869. //Cordinates are same?
  870. && l1==l2 && r1==r2 && t1==t2 && b1==b2 ) {
  871. Tok1.wReserved = 0;
  872. } else {
  873. //If token is Version stamp and szTexts is "Translation",
  874. //it is 1.0 version format. So ignore it.
  875. if ( Tok1.wType == ID_RT_VERSION
  876. && !_tcscmp( Tok2.szText, TEXT("Translation")) ) {
  877. if ( Tok2.szText != NULL ) {
  878. RLFREE( Tok2.szText);
  879. }
  880. Tok2.szText = NULL;
  881. Tok2.wFlag = 1;
  882. goto IGNORETRANSLATION;
  883. }
  884. bChangedText = bChangesDetected = TRUE;
  885. Tok1.wReserved = ST_CHANGED|ST_NEW;
  886. Tok2.wReserved = ST_CHANGED;
  887. }
  888. } else {
  889. Tok1.wReserved = 0;
  890. }
  891. } else {
  892. Tok1.wReserved = Tok2.wReserved;
  893. }
  894. } else {
  895. //... Must be a new token (not in current token file)
  896. //If token is Version stump, and old mtk is 1.0 data file, convert it.
  897. if ( Tok1.wType==ID_RT_VERSION ) {
  898. Tok2.szText = NULL;
  899. Tok2.wFlag = 1;
  900. _tcscpy( Tok2.szName, TEXT("VALUE") );
  901. if ( FindToken( fCurTokFile, &Tok2, 0)
  902. && ! lstrcmp( Tok1.szText, Tok2.szText) ) {
  903. Tok1.wReserved = Tok2.wReserved;
  904. } else
  905. Tok1.wReserved = ST_TRANSLATED | ST_DIRTY;
  906. } else {
  907. Tok1.wReserved = ST_TRANSLATED | ST_DIRTY;
  908. }
  909. bChangesDetected = TRUE;
  910. }
  911. //... Copy token from new token file to final token
  912. //... file. If a change was detected, then copy the
  913. //... original token (from the "current" token file
  914. //... into the final token file.
  915. PutToken( fNewTokFile, &Tok1);
  916. RLFREE( Tok1.szText);
  917. if ( bChangedText ) {
  918. PutToken( fNewTokFile, &Tok2);
  919. // now delta tokens follow translation tokens
  920. }
  921. if ( Tok2.szText != NULL ) {
  922. RLFREE( Tok2.szText);
  923. }
  924. }
  925. if ( ! bChangesDetected ) {
  926. // We have to test to be sure that no tokens were deleted
  927. // since we know that none changed.
  928. rewind( fCurTokFile);
  929. //... Look for tokens that exist in the current
  930. //... token file that do not exist in the token
  931. //... file created from the updated .EXE.
  932. while ( GetToken( fCurTokFile, &Tok1) == 0 ) {
  933. --cTokenCount;
  934. RLFREE( Tok1.szText);
  935. }
  936. if ( cTokenCount != 0 ) {
  937. bChangesDetected = TRUE;
  938. }
  939. }
  940. return ( bChangesDetected);
  941. }
  942. void MakeNewExt(char *NewName, char *OldName, char *ext)
  943. {
  944. char drive[_MAX_DRIVE];
  945. char dir[_MAX_DIR];
  946. char fname[_MAX_FNAME]; // dummy vars to hold file name info
  947. char dext[_MAX_EXT];
  948. // Split obj file name into filename and extention
  949. _splitpath(OldName, drive, dir, fname, dext);
  950. // Make new file name with new ext extention
  951. _makepath(NewName, drive, dir, fname, ext);
  952. }
  953. //......................................................................
  954. //...
  955. //... Check to see if the given file name *should* be an EXE
  956. //...
  957. //... Return: TRUE if it should, else FALSE.
  958. static BOOL ShouldBeAnExe( PCHAR szFileName)
  959. {
  960. PCHAR psz;
  961. if ( (psz = strrchr( szFileName, '.')) != NULL ) {
  962. if ( IsRes( szFileName) ) {
  963. return ( FALSE);
  964. } else if ( lstrcmpiA( psz, ".exe") == 0
  965. || lstrcmpiA( psz, ".dll") == 0
  966. || lstrcmpiA( psz, ".com") == 0
  967. || lstrcmpiA( psz, ".scr") == 0
  968. || lstrcmpiA( psz, ".cpl") == 0 ) {
  969. return ( TRUE);
  970. }
  971. //... Because we think this case of filename
  972. //... would be not executable file rather than res file.
  973. else if ( lstrcmpiA( psz, ".tmp") == 0 ) { //for tmp file created by Dlgedit
  974. return ( FALSE );
  975. } else {
  976. return ( TRUE );
  977. }
  978. }
  979. return ( FALSE);
  980. }
  981. //.........................................................
  982. //...
  983. //... If the named file exists and is not empty, return FALSE, else TRUE.
  984. static BOOL NotExistsOrIsEmpty( PCHAR pszFileName)
  985. {
  986. BOOL fRC = TRUE;
  987. int hFile = -1;
  988. //... Does file not exist?
  989. if ( _access( pszFileName, 0) == 0 ) {
  990. //... No, file exists. Open it.
  991. if ( (hFile = _open( pszFileName, _O_RDONLY)) != -1 ) {
  992. //... Is it Empty?
  993. if ( _filelength( hFile) == 0L ) {
  994. fRC = TRUE; //... Yes, file is empty.
  995. } else {
  996. fRC = FALSE; //... No, file is not empty.
  997. }
  998. _close( hFile);
  999. } else {
  1000. QuitA( IDS_ENGERR_01, "non-empty", pszFileName);
  1001. }
  1002. } else {
  1003. fRC = TRUE; //... Yes, file does not exist.
  1004. }
  1005. return ( fRC);
  1006. }