windows-nt/Source/XPSP1/NT/sdktools/generr/generr.c

433 lines
9.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}