|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
generr.c
Abstract:
This module contains code to generate the NT status code to DOS error code table that is used by the runtime to translate status codes.
Author:
David N. Cutler (davec) 2-Dec-1992
Revision History:
--*/
#include <windows.h>
#include "stdio.h"
#include "stdarg.h"
#include "stdlib.h"
//
// Ensure that the Registry ERROR_SUCCESS error code and the
// NO_ERROR error code remain equal and zero.
//
#if ERROR_SUCCESS != 0 || NO_ERROR != 0
#error Invalid value for ERROR_SUCCESS.
#endif
//
// The following error code table contains paired entries in a singly
// dimensioned array. The first member of a paired entry is an NT status
// code and the second member is the DOS error code that it translates to.
//
// To add a value to this table simply insert the NT status/DOS error code
// pair anywhere is the table. If multiple NT status codes map to a single
// DOS error code, then insert a paired entry for each of the code pairs.
//
#ifdef i386
#pragma warning (4:4018) // lower to -W4
#endif
LONG UNALIGNED *CodePairs; ULONG TableSize;
//
// Define run table entry structure.
//
typedef struct _RUN_ENTRY { ULONG BaseCode; USHORT RunLength; USHORT CodeSize; } RUN_ENTRY, *PRUN_ENTRY;
//
// Define forward referenced procedure prptotypes.
//
ULONG ComputeCodeSize ( IN ULONG Start, IN ULONG Length );
ULONG ComputeRunLength ( IN ULONG Start );
LONG UNALIGNED * ReadErrorTable( IN FILE *InFile, OUT PULONG TableSize );
//
// This program generates a header file that is included by the error
// translation module in ntos/rtl.
//
int _cdecl main (argc, argv) int argc; char *argv[];
{
ULONG Count; ULONG Index1; ULONG Index2; ULONG Length; FILE *OutFile; PCHAR OutName; FILE *InFile; PCHAR InName; RUN_ENTRY *RunTable; ULONG Size; ULONG Temp;
if (argc != 3) { fprintf(stderr, "Usage: GENERR <input_obj> <output_h>\n"); perror("GENERR"); exit(1); }
//
// Open file for input.
//
InName = argv[1]; InFile = fopen(InName, "rb"); if (InFile == NULL) { fprintf(stderr, "GENERR: Cannot open %s for reading.\n", InName); perror("GENERR"); exit(1); }
CodePairs = ReadErrorTable( InFile, &TableSize ); if (CodePairs == NULL) { fprintf(stderr, "CodePairs[] not found in %s.\n", InName); perror("GENERR"); exit(1); }
fclose(InFile);
RunTable = malloc(TableSize / 4); if (RunTable == NULL) { fprintf(stderr, "Out of memory.\n"); perror("GENERR"); exit(1); }
//
// Create file for output.
//
OutName = argv[2]; fprintf(stderr, "GENERR: Writing %s header file.\n", OutName ); OutFile = fopen(OutName, "w"); if (OutFile == NULL) { fprintf(stderr, "GENERR: Cannot open %s for writing.\n", OutName); perror("GENERR"); exit(1); }
//
// Sort the code translation table.
//
for (Index1 = 0; Index1 < (TableSize / 4); Index1 += 2) { for (Index2 = Index1; Index2 < (TableSize / 4); Index2 += 2) { if ((ULONG)CodePairs[Index2] < (ULONG)CodePairs[Index1]) { Temp = CodePairs[Index1]; CodePairs[Index1] = CodePairs[Index2]; CodePairs[Index2] = Temp; Temp = CodePairs[Index1 + 1]; CodePairs[Index1 + 1] = CodePairs[Index2 + 1]; CodePairs[Index2 + 1] = Temp; } } }
//
// Output the initial structure definitions and the translation
// table declaration.
//
fprintf(OutFile, "//\n"); fprintf(OutFile, "// Define run length table entry structure type.\n"); fprintf(OutFile, "//\n"); fprintf(OutFile, "\n"); fprintf(OutFile, "typedef struct _RUN_ENTRY {\n"); fprintf(OutFile, " ULONG BaseCode;\n"); fprintf(OutFile, " USHORT RunLength;\n"); fprintf(OutFile, " USHORT CodeSize;\n"); fprintf(OutFile, "} RUN_ENTRY, *PRUN_ENTRY;\n");
fprintf(OutFile, "\n"); fprintf(OutFile, "//\n"); fprintf(OutFile, "// Declare translation table array.\n"); fprintf(OutFile, "//\n"); fprintf(OutFile, "\n"); fprintf(OutFile, "CONST USHORT RtlpStatusTable[] = {"); fprintf(OutFile, "\n ");
//
// Calculate the run length entries and output the translation table
// entries.
//
Count = 0; Index1 = 0; Index2 = 0; do { Length = ComputeRunLength(Index1); Size = ComputeCodeSize(Index1, Length); RunTable[Index2].BaseCode = CodePairs[Index1]; RunTable[Index2].RunLength = (USHORT)Length; RunTable[Index2].CodeSize = (USHORT)Size; Index2 += 1; do { if (Size == 1) { Count += 1; fprintf(OutFile, "0x%04lx, ", CodePairs[Index1 + 1]);
} else { Count += 2; fprintf(OutFile, "0x%04lx, 0x%04lx, ", CodePairs[Index1 + 1] & 0xffff, (ULONG)CodePairs[Index1 + 1] >> 16); }
if (Count > 6) { Count = 0; fprintf(OutFile, "\n "); }
Index1 += 2; Length -= 1; } while (Length > 0); } while (Index1 < (TableSize / 4));
fprintf(OutFile, "0x0};\n");
//
// Output the run length table declaration.
//
fprintf(OutFile, "\n"); fprintf(OutFile, "//\n"); fprintf(OutFile, "// Declare run length table array.\n"); fprintf(OutFile, "//\n"); fprintf(OutFile, "\n"); fprintf(OutFile, "CONST RUN_ENTRY RtlpRunTable[] = {"); fprintf(OutFile, "\n");
//
// Output the run length table entires.
//
for (Index1 = 0; Index1 < Index2; Index1 += 1) { fprintf(OutFile, " {0x%08lx, 0x%04lx, 0x%04lx},\n", RunTable[Index1].BaseCode, RunTable[Index1].RunLength, RunTable[Index1].CodeSize); }
fprintf(OutFile, " {0x0, 0x0, 0x0}};\n");
//
// Close output file.
//
fclose(OutFile); return 0; }
ULONG ComputeCodeSize ( IN ULONG Start, IN ULONG Length )
//
// This function computes the size of the code entries required for the
// specified run and returns the length in words.
//
{
ULONG Index;
for (Index = Start; Index < (Start + (Length * 2)); Index += 2) { if (((ULONG)CodePairs[Index + 1] >> 16) != 0) { return 2; } }
return 1; }
ULONG ComputeRunLength ( IN ULONG Start )
//
// This function locates the next set of monotonically increasing status
// codes values and returns the length of the run.
//
{
ULONG Index; ULONG Length;
Length = 1; for (Index = Start + 2; Index < (TableSize / 4); Index += 2) { if ((ULONG)CodePairs[Index] != ((ULONG)CodePairs[Index - 2] + 1)) { break; }
Length += 1; }
return Length; }
LONG UNALIGNED * ReadErrorTable( IN FILE *InFile, OUT PULONG TableSize ) { ULONG fileSize; PLONG fileBuf; LONG UNALIGNED *searchEnd; LONG pattern[4] = { 'Begi','n ge','nerr',' tbl' }; LONG UNALIGNED *p; ULONG result; ULONG i; LONG UNALIGNED *tableStart;
//
// Get the file size and allocate a buffer large enough for it.
//
if (fseek( InFile, 0, SEEK_END ) == -1) { return NULL; } fileSize = ftell( InFile ); if (fileSize == 0) { return NULL; }
fileBuf = malloc( fileSize ); if (fileBuf == NULL) { return NULL; }
//
// Read the file into the buffer
//
if (fseek( InFile, 0, SEEK_SET ) == -1) { free (fileBuf); return NULL; } result = fread( fileBuf, fileSize, 1, InFile ); if (result != 1) { free (fileBuf); return NULL; } searchEnd = fileBuf + (fileSize - sizeof(pattern)) / sizeof(ULONG);
//
// Step through the buffer looking for our pattern.
//
p = fileBuf; while (p < searchEnd) {
//
// Match in this position?
//
for (i = 0; i < 4; i++) {
if (*(p + i) != pattern[i]) {
//
// No match here
//
break; } }
if (i == 4) {
//
// Found the pattern. Now find out how big the table is. We
// do this by searching for the last pair, which has
// 0xffffffff as its first element.
//
p += 4;
tableStart = p; while (p < searchEnd) {
if (*p == 0xffffffff) {
//
// Found the terminating pair.
//
*TableSize = (ULONG)((p - tableStart + 2) * sizeof(ULONG)); return tableStart; }
p += 2; }
free (fileBuf); return NULL; }
//
// Next position
//
p = (PLONG)((ULONG_PTR)p + 1); }
free (fileBuf); return NULL; }
|