433 lines
9.2 KiB
C
433 lines
9.2 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|