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.

680 lines
21 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. convfont.c
  5. Abstract:
  6. This module contains the code that implements a bootfont.bin conversion
  7. program.
  8. This tool converts a bootfont.bin that is circa windows 2000 \ nt4 and
  9. converts it into the windows whistler format. The new format includes a
  10. column of information on unicode translation of MBCS characters.
  11. Author:
  12. Matt Holle (MattH) 8-March-2001
  13. Revision History:
  14. --*/
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <tchar.h>
  19. #include <locale.h>
  20. // #include "..\..\lib\i386\bootfont.h"
  21. // #include "fonttable.h"
  22. #define BYTES_PER_SBCS_CHARACTER (17)
  23. #define BYTES_PER_DBCS_CHARACTER (34)
  24. //
  25. // Define maximum number of dbcs lead byte ranges we support.
  26. //
  27. #define MAX_DBCS_RANGE 5
  28. //
  29. // Define signature value.
  30. //
  31. #define BOOTFONTBIN_SIGNATURE 0x5465644d
  32. //
  33. // Define structure used as a header for the bootfont.bin file.
  34. //
  35. typedef struct _BOOTFONTBIN_HEADER {
  36. //
  37. // Signature. Must be BOOTFONTBIN_SIGNATURE.
  38. //
  39. ULONG Signature;
  40. //
  41. // Language id of the language supported by this font.
  42. // This should match the language id of resources in msgs.xxx.
  43. //
  44. ULONG LanguageId;
  45. //
  46. // Number of sbcs characters and dbcs characters contained in the file.
  47. //
  48. unsigned NumSbcsChars;
  49. unsigned NumDbcsChars;
  50. //
  51. // Offsets within the file to the images.
  52. //
  53. unsigned SbcsOffset;
  54. unsigned DbcsOffset;
  55. //
  56. // Total sizes of the images.
  57. //
  58. unsigned SbcsEntriesTotalSize;
  59. unsigned DbcsEntriesTotalSize;
  60. //
  61. // Dbcs lead byte table. Must contain a pair of 0's to indicate the end.
  62. //
  63. UCHAR DbcsLeadTable[(MAX_DBCS_RANGE+1)*2];
  64. //
  65. // Height values for the font.
  66. // CharacterImageHeight is the height in scan lines/pixels of the
  67. // font image. Each character is drawn with additional 'padding'
  68. // lines on the top and bottom, whose sizes are also contained here.
  69. //
  70. UCHAR CharacterImageHeight;
  71. UCHAR CharacterTopPad;
  72. UCHAR CharacterBottomPad;
  73. //
  74. // Width values for the font. These values contain the width in pixels
  75. // of a single byte character and double byte character.
  76. //
  77. // NOTE: CURRENTLY THE SINGLE BYTE WIDTH *MUST* BE 8 AND THE DOUBLE BYTE
  78. // WIDTH *MUST* BE 16!!!
  79. //
  80. UCHAR CharacterImageSbcsWidth;
  81. UCHAR CharacterImageDbcsWidth;
  82. } BOOTFONTBIN_HEADER, *PBOOTFONTBIN_HEADER;
  83. int
  84. __cdecl
  85. main(
  86. IN int argc,
  87. IN char *argv[]
  88. )
  89. {
  90. HANDLE hInputFile = INVALID_HANDLE_VALUE;
  91. HANDLE hOutputFile = INVALID_HANDLE_VALUE;
  92. DWORD BytesWritten = 0;
  93. BOOL b;
  94. BOOL Verbose = FALSE;
  95. BOOTFONTBIN_HEADER *pHeader;
  96. ULONG u = 0;
  97. ULONG i = 0;
  98. UCHAR *SBCSFontImage;
  99. UCHAR *DBCSFontImage;
  100. UCHAR *Operator;
  101. WCHAR UnicodeValue;
  102. UCHAR *ExistingFileBuffer = NULL;
  103. BOOLEAN DumpIt = FALSE;
  104. if( !strcmp(argv[argc-1], "-v") ) {
  105. Verbose = TRUE;
  106. } else {
  107. if( !strcmp(argv[argc-1], "-d") ) {
  108. DumpIt = TRUE;
  109. Verbose = TRUE;
  110. }
  111. }
  112. if( !DumpIt && (argc < 3)) {
  113. fprintf(stderr,"Usage: %s <inputfile> <outputfile> [-v] [-d]\n",argv[0]);
  114. fprintf(stderr,"\n" );
  115. fprintf(stderr," Where <inputfile> is a bootfont.bin file to be translated\n");
  116. fprintf(stderr," into the new format\n");
  117. fprintf(stderr,"\n" );
  118. fprintf(stderr," <outputfile> is the destination file.\n" );
  119. fprintf(stderr,"\n" );
  120. fprintf(stderr," -v operate in a verbose manner.\n" );
  121. fprintf(stderr,"\n" );
  122. fprintf(stderr," -d dump the contents of <inputfile> in a readable format.\n" );
  123. fprintf(stderr," Here, no outputfile need be specified.\n" );
  124. fprintf(stderr,"\n" );
  125. fprintf(stderr," NOTE: You must have the proper locale files installed and configured on your\n" );
  126. fprintf(stderr," machine. To do this, start up intl.cpl, go to the Advanced tab and select.\n" );
  127. fprintf(stderr," the Language setting to correspond to the language of the bootfont.bin file.\n" );
  128. fprintf(stderr," Make sure you check the 'Apply all settings to the current...' tab too.\n" );
  129. fprintf(stderr,"\n" );
  130. goto Cleanup;
  131. }
  132. if( Verbose && !DumpIt ) {
  133. //
  134. // spew input.
  135. //
  136. printf( "Running in Verbose Mode\n" );
  137. printf( "InputFile: %s\n", argv[1] );
  138. printf( "OutputFile: %s\n", argv[2] );
  139. }
  140. //
  141. // Open the input file.
  142. //
  143. hInputFile = CreateFile( argv[1],
  144. GENERIC_READ,
  145. FILE_SHARE_READ,
  146. NULL,
  147. OPEN_EXISTING,
  148. 0,
  149. NULL );
  150. if(hInputFile == INVALID_HANDLE_VALUE) {
  151. fprintf( stderr, "\nUnable to open input file %s (%u)\n", argv[1], GetLastError());
  152. goto Cleanup;
  153. }
  154. if( !DumpIt ) {
  155. //
  156. // Create the output file.
  157. //
  158. hOutputFile = CreateFile( argv[2],
  159. FILE_GENERIC_WRITE,
  160. 0,
  161. NULL,
  162. CREATE_ALWAYS,
  163. 0,
  164. NULL );
  165. if(hOutputFile == INVALID_HANDLE_VALUE) {
  166. fprintf( stderr, "\nUnable to create output file %s (%u)\n", argv[2], GetLastError());
  167. goto Cleanup;
  168. }
  169. }
  170. //
  171. // Figure out how big the existing file is.
  172. //
  173. BytesWritten = GetFileSize( hInputFile, NULL );
  174. if( BytesWritten == (DWORD)(-1) ) {
  175. fprintf( stderr, "\nAn error occured getting the file size.\n" );
  176. goto Cleanup;
  177. }
  178. //
  179. // Allocate a buffer for the file.
  180. //
  181. ExistingFileBuffer = malloc(BytesWritten + 3);
  182. b = ReadFile( hInputFile,
  183. ExistingFileBuffer,
  184. BytesWritten,
  185. &i,
  186. NULL );
  187. CloseHandle( hInputFile );
  188. hInputFile = INVALID_HANDLE_VALUE;
  189. if( !b ) {
  190. fprintf( stderr, "\nError reading input file %s\n", argv[1] );
  191. goto Cleanup;
  192. }
  193. //
  194. // Read in the header.
  195. //
  196. pHeader = (BOOTFONTBIN_HEADER *)ExistingFileBuffer;
  197. // Tell the user about the bootfont.bin file that we read.
  198. if( Verbose ) {
  199. printf( "Size of BOOTFONTBIN_HEADER: %d\n", sizeof(BOOTFONTBIN_HEADER) );
  200. printf( "\nRead Header Data:\n" );
  201. printf( "=================\n" );
  202. printf( "Header.Signature: 0x%08lx\n", pHeader->Signature );
  203. printf( "Header.LanguageId: 0x%08lx\n", pHeader->LanguageId );
  204. printf( "Header.NumSbcsChars: 0x%08lx\n", pHeader->NumSbcsChars );
  205. printf( "Header.NumDbcsChars: 0x%08lx\n", pHeader->NumDbcsChars );
  206. printf( "Header.SbcsOffset: 0x%08lx\n", pHeader->SbcsOffset );
  207. printf( "Header.DbcsOffset: 0x%08lx\n", pHeader->DbcsOffset );
  208. printf( "Header.SbcsEntriesTotalSize: 0x%08lx\n", pHeader->SbcsEntriesTotalSize );
  209. printf( "Header.DbcsEntriesTotalSize: 0x%08lx\n", pHeader->DbcsEntriesTotalSize );
  210. printf( "Header.CharacterImageHeight: 0x%02lx\n", pHeader->CharacterImageHeight );
  211. printf( "Header.CharacterTopPad: 0x%02lx\n", pHeader->CharacterTopPad );
  212. printf( "Header.CharacterBottomPad: 0x%02lx\n", pHeader->CharacterBottomPad );
  213. printf( "Header.CharacterImageSbcsWidth: 0x%02lx\n", pHeader->CharacterImageSbcsWidth );
  214. printf( "Header.CharacterImageDbcsWidth: 0x%02lx\n", pHeader->CharacterImageDbcsWidth );
  215. printf( "\n" );
  216. }
  217. if( DumpIt ) {
  218. ULONG j;
  219. //
  220. // Just Dump the contents of the bootfont.bin file in
  221. // a more readable format.
  222. //
  223. SBCSFontImage = ExistingFileBuffer + pHeader->SbcsOffset;
  224. DBCSFontImage = ExistingFileBuffer + pHeader->DbcsOffset;
  225. i = pHeader->SbcsEntriesTotalSize / pHeader->NumSbcsChars;
  226. if( i == BYTES_PER_SBCS_CHARACTER+2 ) {
  227. printf( "Dumping contents of newstyled file %s\n", argv[1] );
  228. printf( "\nSBCS Values:\n" );
  229. printf( "============\n" );
  230. for( u=0; u < pHeader->NumSbcsChars; u++ ) {
  231. // jump to the u-th element. Each element contains BYTES_PER_SBCS_CHARACTER
  232. // bytes, plus another 2 bytes for the UNICODE value sitting at the end
  233. // of the entry.
  234. Operator = SBCSFontImage + (u * (BYTES_PER_SBCS_CHARACTER+2));
  235. printf( "SBCS Char Code: 0x%02lx\n", *Operator );
  236. printf( " Unicode Code: 0x%04lx\n", *(WCHAR *)(Operator + BYTES_PER_SBCS_CHARACTER) );
  237. printf( " Glyph: " );
  238. Operator += 1;
  239. for( j = 1; j < BYTES_PER_SBCS_CHARACTER; j++ ) {
  240. printf( "0x%02x ", *Operator );
  241. Operator++;
  242. }
  243. printf( "\n\n" );
  244. }
  245. printf( "\nDBCS Values:\n" );
  246. printf( "============\n" );
  247. for( u=0; u < pHeader->NumDbcsChars; u++ ) {
  248. // jump to the u-th element. Each element contains BYTES_PER_DBCS_CHARACTER
  249. // bytes, plus another 2 bytes for the UNICODE value sitting at the end
  250. // of the entry.
  251. Operator = DBCSFontImage + (u * (BYTES_PER_DBCS_CHARACTER+2));
  252. printf( "DBCS Char Code: 0x%04lx\n", *Operator );
  253. printf( " Unicode Code: 0x%04lx\n", *(WCHAR *)(Operator + BYTES_PER_DBCS_CHARACTER) );
  254. printf( " Glyph: " );
  255. Operator += 2;
  256. for( j = 1; j < BYTES_PER_DBCS_CHARACTER; j++ ) {
  257. printf( "0x%02x ", *Operator );
  258. Operator++;
  259. }
  260. printf( "\n\n" );
  261. }
  262. printf( "\n\n" );
  263. goto Cleanup;
  264. } else {
  265. printf( "Dumping contents of oldstyle file %s\n", argv[1] );
  266. printf( "\nSBCS Values:\n" );
  267. printf( "============\n" );
  268. for( u=0; u < pHeader->NumSbcsChars; u++ ) {
  269. // jump to the u-th element. Each element contains BYTES_PER_SBCS_CHARACTER
  270. // bytes.
  271. Operator = SBCSFontImage + (u * (BYTES_PER_SBCS_CHARACTER));
  272. printf( "SBCS Char Code: 0x%02lx\n", *Operator );
  273. printf( " Glyph: " );
  274. Operator += 1;
  275. for( j = 1; j < BYTES_PER_SBCS_CHARACTER; j++ ) {
  276. printf( "0x%02x ", *Operator );
  277. Operator++;
  278. }
  279. printf( "\n\n" );
  280. }
  281. printf( "\nDBCS Values:\n" );
  282. printf( "============\n" );
  283. for( u=0; u < pHeader->NumDbcsChars; u++ ) {
  284. // jump to the u-th element. Each element contains BYTES_PER_DBCS_CHARACTER
  285. // bytes.
  286. Operator = DBCSFontImage + (u * (BYTES_PER_DBCS_CHARACTER));
  287. printf( "DBCS Char Code: 0x%04lx\n", *Operator );
  288. printf( " Glyph: " );
  289. Operator += 2;
  290. for( j = 1; j < BYTES_PER_DBCS_CHARACTER; j++ ) {
  291. printf( "0x%02x ", *Operator );
  292. Operator++;
  293. }
  294. printf( "\n\n" );
  295. }
  296. printf( "\n\n" );
  297. goto Cleanup;
  298. }
  299. }
  300. //
  301. // Verify the header's signature.
  302. //
  303. if( pHeader->Signature != BOOTFONTBIN_SIGNATURE ) {
  304. fprintf( stderr, "\nInputfile %s does not have a valid signature\n", argv[1] );
  305. goto Cleanup;
  306. }
  307. //
  308. // Verify that this isn't already in the new format. We can test this by
  309. // looking at how many SBCS characters are stored in here. Then looking at
  310. // how big the header says the SBCS data section is.
  311. //
  312. // We know that for each SBCS character, we would have:
  313. // 1 byte for the SBCS character
  314. // 16 bytes for the glyph
  315. //
  316. // If it's an old-style bootfont.bin, the total size of the SBCS data block
  317. // should be 17 times bigger than the number of SBCS characters. However, if
  318. // it's a new-style bootfont.bin, it will be 19 times bigger because we've
  319. // added 2 bytes onto the end of each SBCS entry (for a total of 19 bytes).
  320. //
  321. i = pHeader->SbcsEntriesTotalSize / pHeader->NumSbcsChars;
  322. if( i != BYTES_PER_SBCS_CHARACTER ) {
  323. if( i == (BYTES_PER_SBCS_CHARACTER+2) ) {
  324. fprintf( stderr, "\nThis input file is already in the new format.\n" );
  325. } else {
  326. fprintf( stderr, "\nThis input file has an abnormal number of bytes per SBCS character (%d)\n", i );
  327. }
  328. goto Cleanup;
  329. }
  330. //
  331. // Now check the number of bytes per DBCS character.
  332. //
  333. i = pHeader->DbcsEntriesTotalSize / pHeader->NumDbcsChars;
  334. if( i != BYTES_PER_DBCS_CHARACTER ) {
  335. if( i == (BYTES_PER_DBCS_CHARACTER+2) ) {
  336. fprintf( stderr, "\nThis input file is already in the new format.\n" );
  337. } else {
  338. fprintf( stderr, "\nThis input file has an abnormal number of bytes per DBCS character (%d)\n", i );
  339. }
  340. goto Cleanup;
  341. }
  342. //
  343. // Looking good.
  344. //
  345. printf( "Processing %s...\n", argv[1] );
  346. //
  347. // Before updating and writing out the header, we need to examine
  348. // the header and remember where the SBCS and DBCS data blocks are
  349. // in our image.
  350. //
  351. SBCSFontImage = ExistingFileBuffer + pHeader->SbcsOffset;
  352. DBCSFontImage = ExistingFileBuffer + pHeader->DbcsOffset;
  353. //
  354. // Fixup the Header, then write it out.
  355. //
  356. // Add 2 bytes for each entry for our unicode appendage
  357. pHeader->SbcsEntriesTotalSize += (pHeader->NumSbcsChars * 2);
  358. pHeader->DbcsEntriesTotalSize += (pHeader->NumDbcsChars * 2);
  359. // The offset to the DBCS data block will have changed now too.
  360. pHeader->DbcsOffset = pHeader->SbcsOffset + pHeader->SbcsEntriesTotalSize;
  361. // Tell the user about the bootfont.bin file that we read.
  362. if( Verbose ) {
  363. printf( "\nUpdated Header Data:\n" );
  364. printf( "======================\n" );
  365. printf( "Header.Signature: 0x%08lx\n", pHeader->Signature );
  366. printf( "Header.LanguageId: 0x%08lx\n", pHeader->LanguageId );
  367. printf( "Header.NumSbcsChars: 0x%08lx\n", pHeader->NumSbcsChars );
  368. printf( "Header.NumDbcsChars: 0x%08lx\n", pHeader->NumDbcsChars );
  369. printf( "Header.SbcsOffset: 0x%08lx\n", pHeader->SbcsOffset );
  370. printf( "Header.DbcsOffset: 0x%08lx\n", pHeader->DbcsOffset );
  371. printf( "Header.SbcsEntriesTotalSize: 0x%08lx\n", pHeader->SbcsEntriesTotalSize );
  372. printf( "Header.DbcsEntriesTotalSize: 0x%08lx\n", pHeader->DbcsEntriesTotalSize );
  373. printf( "\n" );
  374. }
  375. //
  376. // Write the header.
  377. //
  378. b = WriteFile( hOutputFile,
  379. pHeader,
  380. sizeof(BOOTFONTBIN_HEADER),
  381. &BytesWritten,
  382. NULL );
  383. if(!b) {
  384. fprintf( stderr, "\nError writing output file %s (%u)\n", argv[2], GetLastError());
  385. goto Cleanup;
  386. }
  387. //
  388. // Write the sbcs images.
  389. //
  390. if( !Verbose ) {
  391. printf( "Operating on SBCS character code: 0x00" );
  392. }
  393. for( u=0; u < pHeader->NumSbcsChars; u++ ) {
  394. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  395. // glyph.
  396. Operator = SBCSFontImage + (u * BYTES_PER_SBCS_CHARACTER);
  397. b = WriteFile( hOutputFile,
  398. Operator,
  399. BYTES_PER_SBCS_CHARACTER,
  400. &BytesWritten,
  401. NULL );
  402. if( !b ) {
  403. fprintf( stderr, "\nFailed to write SBCS character data.\n" );
  404. goto Cleanup;
  405. }
  406. //
  407. // We must use MultiByteToWideChar to convert from SBCS to unicode.
  408. //
  409. // MultiByteToWideChar doesn't seem to work when converting
  410. // from DBCS to unicode, so there we use mbtowc.
  411. //
  412. #if 0
  413. if( !mbtowc( (WCHAR *)&UnicodeValue, Operator, 1 ) ) {
  414. #else
  415. if( !MultiByteToWideChar( CP_OEMCP,
  416. MB_ERR_INVALID_CHARS,
  417. Operator,
  418. 1,
  419. (WCHAR *)&UnicodeValue,
  420. sizeof(WCHAR) ) ) {
  421. #endif
  422. UnicodeValue = 0x3F;
  423. if( Verbose ) {
  424. fprintf( stderr, "\nFailed to convert SBCS character 0x%02lx to a unicode value. Using '?' character.\n", *Operator );
  425. }
  426. }
  427. if( Verbose ) {
  428. printf( "Converting SBCS character code: 0x%02lx to a unicode value: 0x%04lx\n", *Operator, UnicodeValue );
  429. } else {
  430. printf( "\b\b\b\b0x%02lx", *Operator );
  431. }
  432. b = WriteFile( hOutputFile,
  433. &UnicodeValue,
  434. sizeof(USHORT),
  435. &BytesWritten,
  436. NULL );
  437. if( !b ) {
  438. fprintf( stderr, "\nFailed to write SBCS encoded UNICODE value.\n" );
  439. goto Cleanup;
  440. }
  441. }
  442. printf( "\nCompleted processing %d SBCS characters.\n\n", pHeader->NumSbcsChars );
  443. //
  444. // Write the dbcs images.
  445. //
  446. if( !Verbose ) {
  447. printf( "Operating on DBCS character code: 0x0000" );
  448. }
  449. for( u=0; u < pHeader->NumDbcsChars; u++ ) {
  450. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  451. // glyph.
  452. Operator = DBCSFontImage + (u * BYTES_PER_DBCS_CHARACTER);
  453. b = WriteFile( hOutputFile,
  454. Operator,
  455. BYTES_PER_DBCS_CHARACTER,
  456. &BytesWritten,
  457. NULL );
  458. if( !b || (BytesWritten != BYTES_PER_DBCS_CHARACTER) ) {
  459. fprintf( stderr, "\nFailed to write DBCS character data.\n" );
  460. goto Cleanup;
  461. }
  462. //
  463. // We must use mbtowc to convert from DBCS to unicode.
  464. //
  465. // Whereas, mbtowc doesn't seem to work when converting
  466. // from SBCS to unicode, so there we use MultiByteToWideChar.
  467. //
  468. #if 0
  469. if( !mbtowc( (WCHAR *)&UnicodeValue, Operator, 2 ) ) {
  470. #else
  471. if( !MultiByteToWideChar( CP_OEMCP,
  472. MB_ERR_INVALID_CHARS,
  473. Operator,
  474. 2,
  475. (WCHAR *)&UnicodeValue,
  476. sizeof(WCHAR) ) ) {
  477. #endif
  478. UnicodeValue = 0x3F;
  479. if( Verbose ) {
  480. fprintf( stderr, "\nFailed to convert DBCS character 0x%04lx to a unicode value. Using '?' character.\n", *(WCHAR *)Operator );
  481. }
  482. }
  483. if( Verbose ) {
  484. printf( "Converting DBCS character code: 0x%04lx to Unicode value: 0x%04lx\n", *(WCHAR *)Operator, UnicodeValue );
  485. } else {
  486. printf( "\b\b\b\b\b\b0x%04lx", *(WCHAR *)Operator );
  487. }
  488. b = WriteFile( hOutputFile,
  489. &UnicodeValue,
  490. sizeof(WCHAR),
  491. &BytesWritten,
  492. NULL );
  493. if( !b || (BytesWritten != sizeof(WCHAR)) ) {
  494. fprintf( stderr, "\nFailed to write DBCS encoded UNICODE value.\n" );
  495. goto Cleanup;
  496. }
  497. }
  498. printf( "\nCompleted processing %d DBCS characters.\n", pHeader->NumDbcsChars );
  499. printf( "\nSuccessfully Processed file %s to %s.\n", argv[1], argv[2] );
  500. //
  501. // Done.
  502. //
  503. Cleanup:
  504. if( hInputFile != INVALID_HANDLE_VALUE ) {
  505. CloseHandle( hInputFile );
  506. }
  507. if( hOutputFile != INVALID_HANDLE_VALUE ) {
  508. CloseHandle( hOutputFile );
  509. }
  510. if( ExistingFileBuffer != NULL ) {
  511. free( ExistingFileBuffer );
  512. }
  513. return(0);
  514. }