/*++ Copyright (c) 1991 Microsoft Corporation Module Name: mcout.c Abstract: This file contains the output functions of the Win32 Message Compiler (MC) Author: Steve Wood (stevewo) 22-Aug-1991 Revision History: --*/ #include "mc.h" PMESSAGE_BLOCK MessageBlocks = NULL; int NumberOfBlocks = 0; BOOLEAN McBlockMessages( void ) { PMESSAGE_BLOCK p, *pp; PMESSAGE_INFO MessageInfo; pp = &MessageBlocks; p = NULL; MessageInfo = Messages; while (MessageInfo) { if (p) { if (p->HighId+1 == MessageInfo->Id) { p->HighId += 1; } else { pp = &p->Next; } } if (!*pp) { NumberOfBlocks += 1; p = malloc( sizeof( *p ) ); p->Next = NULL; p->LowId = MessageInfo->Id; p->HighId = MessageInfo->Id; p->LowInfo = MessageInfo; *pp = p; } MessageInfo = MessageInfo->Next; } return( TRUE ); } BOOLEAN McWriteBinaryFilesA( void ) { PNAME_INFO LanguageName, *pp; PLANGUAGE_INFO LanguageInfo; PMESSAGE_INFO MessageInfo; PMESSAGE_BLOCK BlockInfo; char *FileName; ULONG cb, cbNeeded; ULONG MessageOffset; MESSAGE_RESOURCE_ENTRY MessageEntry; MESSAGE_RESOURCE_BLOCK MessageBlock; MESSAGE_RESOURCE_DATA MessageData; ULONG Zeroes = 0; ULONG NumberOfMessages; LPBYTE lpBuf; ULONG Size = 256; FileName = BinaryMessageFileName; FileName += strlen( FileName ); lpBuf = malloc( Size ); if (!lpBuf) { McInputErrorA( "Out of memory writing to output file - %s", TRUE, BinaryMessageFileName ); return( FALSE ); } pp = &LanguageNames; while (LanguageName = *pp) { pp = &LanguageName->Next; if (!LanguageName->Used) { continue; } WideCharToMultiByte( CP_OEMCP, 0, LanguageName->Value, -1, FileName, sizeof( BinaryMessageFileName ) - strlen( FileName ), NULL, NULL ); strcat( FileName, ".bin" ); if (!(BinaryMessageFile = fopen( BinaryMessageFileName, "wb" ))) { McInputErrorA( "unable to open output file - %s", TRUE, BinaryMessageFileName ); return( FALSE ); } if (VerboseOutput) { fprintf( stderr, "Writing %s\n", BinaryMessageFileName ); } fprintf( RcInclFile, "LANGUAGE 0x%x,0x%x\r\n", PRIMARYLANGID( LanguageName->Id ), SUBLANGID( LanguageName->Id ) ); fprintf( RcInclFile, "1 11 %s\r\n", FileName ); NumberOfMessages = 0L; MessageData.NumberOfBlocks = NumberOfBlocks; MessageOffset = fwrite( &MessageData, 1, (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_DATA, Blocks[ 0 ] ), BinaryMessageFile ); MessageOffset += NumberOfBlocks * sizeof( MessageBlock ); BlockInfo = MessageBlocks; while (BlockInfo) { MessageBlock.LowId = BlockInfo->LowId; MessageBlock.HighId = BlockInfo->HighId; MessageBlock.OffsetToEntries = MessageOffset; fwrite( &MessageBlock, 1, sizeof( MessageBlock ), BinaryMessageFile ); BlockInfo->InfoLength = 0; MessageInfo = BlockInfo->LowInfo; while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) { LanguageInfo = MessageInfo->MessageText; while (LanguageInfo) { if (LanguageInfo->Id == LanguageName->Id) { break; } else { LanguageInfo = LanguageInfo->Next; } } if (LanguageInfo != NULL) { cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) + WideCharToMultiByte( LanguageName->CodePage, 0, LanguageInfo->Text, LanguageInfo->Length, NULL, 0, NULL, NULL ) + 1; cb = (cb + 3) & ~3; BlockInfo->InfoLength += cb; } else { fprintf( stderr, "MC: No %ws language text for %ws\n", LanguageName->Name, MessageInfo->SymbolicName ); fclose( BinaryMessageFile ); return( FALSE ); } MessageInfo = MessageInfo->Next; } if (VerboseOutput) { fprintf( stderr, " [%08lx .. %08lx] - %lu bytes\n", BlockInfo->LowId, BlockInfo->HighId, BlockInfo->InfoLength ); } MessageOffset += BlockInfo->InfoLength; BlockInfo = BlockInfo->Next; } BlockInfo = MessageBlocks; while (BlockInfo) { MessageInfo = BlockInfo->LowInfo; while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) { LanguageInfo = MessageInfo->MessageText; while (LanguageInfo) { if (LanguageInfo->Id == LanguageName->Id) { break; } else { LanguageInfo = LanguageInfo->Next; } } if (LanguageInfo != NULL) { cbNeeded = WideCharToMultiByte( LanguageName->CodePage, 0, LanguageInfo->Text, LanguageInfo->Length, NULL, 0, NULL, NULL ); cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) + cbNeeded + 1; cb = (cb + 3) & ~3; MessageEntry.Length = (USHORT)cb; MessageEntry.Flags = 0; cb = fwrite( &MessageEntry, 1, (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ), BinaryMessageFile ); if (Size < cbNeeded ) { lpBuf = realloc( lpBuf, cbNeeded ); if (!lpBuf) { McInputErrorA( "Out of memory writing to output file - %s", TRUE, BinaryMessageFileName ); return( FALSE ); } Size = cbNeeded; } WideCharToMultiByte( LanguageName->CodePage, 0, LanguageInfo->Text, LanguageInfo->Length, lpBuf, cbNeeded, NULL, NULL ); cb += fwrite( lpBuf, 1, (size_t)cbNeeded, BinaryMessageFile ); NumberOfMessages++; cb = MessageEntry.Length - cb; if (cb) { fwrite( &Zeroes, 1, (size_t)cb, BinaryMessageFile ); } } MessageInfo = MessageInfo->Next; } BlockInfo = BlockInfo->Next; } if (VerboseOutput) { fprintf( stderr, " Total of %lu messages, %lu bytes\n", NumberOfMessages, ftell( BinaryMessageFile ) ); } fclose( BinaryMessageFile ); McClearArchiveBit( BinaryMessageFileName ); } free( lpBuf ); return( TRUE ); } BOOLEAN McWriteBinaryFilesW( void ) { PNAME_INFO LanguageName, *pp; PLANGUAGE_INFO LanguageInfo; PMESSAGE_INFO MessageInfo; PMESSAGE_BLOCK BlockInfo; char *FileName; ULONG cb; ULONG MessageOffset; MESSAGE_RESOURCE_ENTRY MessageEntry; MESSAGE_RESOURCE_BLOCK MessageBlock; MESSAGE_RESOURCE_DATA MessageData; ULONG Zeroes = 0; ULONG NumberOfMessages; FileName = BinaryMessageFileName; FileName += strlen( FileName ); pp = &LanguageNames; while (LanguageName = *pp) { pp = &LanguageName->Next; if (!LanguageName->Used) { continue; } WideCharToMultiByte( CP_OEMCP, 0, LanguageName->Value, -1, FileName, sizeof( BinaryMessageFileName ), NULL, NULL); strcat( FileName, ".bin" ); if (!(BinaryMessageFile = fopen( BinaryMessageFileName, "wb" ))) { McInputErrorA( "unable to open output file - %s", TRUE, BinaryMessageFileName ); return( FALSE ); } if (VerboseOutput) { fprintf( stderr, "Writing %s\n", BinaryMessageFileName ); } fprintf( RcInclFile, "LANGUAGE 0x%x,0x%x\r\n", PRIMARYLANGID( LanguageName->Id ), SUBLANGID( LanguageName->Id ) ); fprintf( RcInclFile, "1 11 %s\r\n", FileName ); NumberOfMessages = 0L; MessageData.NumberOfBlocks = NumberOfBlocks; MessageOffset = fwrite( &MessageData, 1, (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_DATA, Blocks[ 0 ] ), BinaryMessageFile ); MessageOffset += NumberOfBlocks * sizeof( MessageBlock ); BlockInfo = MessageBlocks; while (BlockInfo) { MessageBlock.LowId = BlockInfo->LowId; MessageBlock.HighId = BlockInfo->HighId; MessageBlock.OffsetToEntries = MessageOffset; fwrite( &MessageBlock, 1, sizeof( MessageBlock ), BinaryMessageFile ); BlockInfo->InfoLength = 0; MessageInfo = BlockInfo->LowInfo; while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) { LanguageInfo = MessageInfo->MessageText; while (LanguageInfo) { if (LanguageInfo->Id == LanguageName->Id) { break; } else { LanguageInfo = LanguageInfo->Next; } } if (LanguageInfo != NULL) { cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) + ( LanguageInfo->Length + 1 ); cb = (cb + 3) & ~3; BlockInfo->InfoLength += cb; } else { fprintf( stderr, "MC: No %ws language text for %ws\n", LanguageName->Name, MessageInfo->SymbolicName ); fclose( BinaryMessageFile ); _unlink( BinaryMessageFileName ); return( FALSE ); } MessageInfo = MessageInfo->Next; } if (VerboseOutput) { fprintf( stderr, " [%08lx .. %08lx] - %lu bytes\n", BlockInfo->LowId, BlockInfo->HighId, BlockInfo->InfoLength ); } MessageOffset += BlockInfo->InfoLength; BlockInfo = BlockInfo->Next; } BlockInfo = MessageBlocks; while (BlockInfo) { MessageInfo = BlockInfo->LowInfo; while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) { LanguageInfo = MessageInfo->MessageText; while (LanguageInfo) { if (LanguageInfo->Id == LanguageName->Id) { break; } else { LanguageInfo = LanguageInfo->Next; } } if (LanguageInfo != NULL) { cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) + ( LanguageInfo->Length + 1 ) ; cb = (cb + 3) & ~3; MessageEntry.Length = (USHORT)cb; MessageEntry.Flags = MESSAGE_RESOURCE_UNICODE; cb = fwrite( &MessageEntry, 1, (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ), BinaryMessageFile ); cb += fwrite( LanguageInfo->Text, 1, (size_t)( LanguageInfo->Length ), BinaryMessageFile ); NumberOfMessages++; cb = MessageEntry.Length - cb; if (cb) { fwrite( &Zeroes, 1, (size_t)cb, BinaryMessageFile ); } } MessageInfo = MessageInfo->Next; } BlockInfo = BlockInfo->Next; } if (VerboseOutput) { fprintf( stderr, " Total of %lu messages, %lu bytes\n", NumberOfMessages, ftell( BinaryMessageFile ) ); } fclose( BinaryMessageFile ); McClearArchiveBit( BinaryMessageFileName ); } return( TRUE ); }