Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

949 lines
22 KiB

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct _tagFILEINFO {
HANDLE hFile;
HANDLE hMap;
LPSTR fptr;
CHAR fname[MAX_PATH];
BOOL bModified ;
} FILEINFO, *PFILEINFO;
typedef struct _IPATH {
struct _IPATH * pIpNext ;
DWORD cipath;
CHAR ipath[100][MAX_PATH];
} IPATH ;
IPATH * pIpath = NULL ;
BOOL bDebug = FALSE ;
BOOL bIgnoreDups = FALSE ;
BOOL bRecurse = FALSE ;
BOOL bVerbose = FALSE ;
FILE * vout = NULL ;
#define BAD_FILE ((DWORD)-1)
BOOL
MapInputFile (
PFILEINFO lpfi
);
BOOL
MapOutputFile (
PFILEINFO lpfi,
DWORD fsize
);
VOID
UnMapInputFile(
PFILEINFO lpfi
);
VOID
UnMapOutputFile(
PFILEINFO lpfi
);
DWORD
FindHeaderFile(
LPSTR HeaderFileName,
BOOL * pbDuplicate
);
VOID
ChangeSourceFile(
LPSTR fname
);
VOID
ProcessFilesInTree(
LPSTR RootPath
);
BOOL
IsValidSourceFile(
LPSTR fname
);
BOOL
CheckOutSourceFile(
LPSTR fname
);
VOID
ChangeSlmSourcesFile(
VOID
);
BOOL
GetIncludePath(
CHAR * Path,
BOOL bForce
);
VOID
FixHeaderFile(
LPSTR HeaderFileName
);
CHAR *
ScanForHashInclude(
CHAR * pch
);
VOID
DisplayDelta (
CHAR * pchFileName,
CHAR * pchHeaderName,
CHAR chNewMark
) ;
BOOL
PushIpath ( void ) ;
BOOL
PopIpath ( void ) ;
void usage (
void
)
{
fprintf( stdout, "\nPCHFIX: make sources and header comply with BUILD\'s rules" ) ;
fprintf( stdout, "\n Command line: pchfix [options]" ) ;
fprintf( stdout, "\n Options: " ) ;
fprintf( stdout, "\n /i ignore multiple mentions of same header file" ) ;
fprintf( stdout, "\n /r recurse into subdirectories" ) ;
fprintf( stdout, "\n /v (verbose) display frequent tracking information" ) ;
fprintf( stdout, "\n /d debug only; write action descriptions to stdout" ) ;
fprintf( stdout, "\n implies /v(erbose)" ) ;
fprintf( stdout, "\n" ) ;
fprintf( stdout, "\nNote: only top-level \"sources\" file is processed." ) ;
fprintf( stdout, "\n" ) ;
}
int _cdecl main ( int argc, char * argv[], char * envp[] )
{
int i ;
for ( i = 1 ; i < argc ; i++ )
{
char * pszOpt = argv[i] ;
int opt = *pszOpt == '/' || *pszOpt == '-' ;
if ( opt )
{
char chOpt = toupper( pszOpt[1] );
switch ( chOpt )
{
case 'I':
//
// Ignore duplicate header file references.
//
bIgnoreDups = TRUE ;
break ;
case 'R':
//
// Enable directory recursion
//
bRecurse = TRUE ;
break ;
case '?':
case 'H':
usage();
exit(1);
break ;
case 'D':
//
// Debug only: output goes to stdout
//
bDebug = TRUE ;
// fall thru to enable verbose output
case 'V':
bVerbose = TRUE ;
vout = stdout ;
break ;
default:
fprintf( stderr, "unrecognized option\n" ) ;
exit(3) ;
break ;
}
}
}
if ( vout == NULL )
{
vout = fopen( "NUL", "w" ) ;
}
if ( ! GetIncludePath( ".\\", TRUE ) )
{
fprintf( stderr, "PCHFIX error: \'.\\sources\' file not found at this level." ) ;
exit(3) ;
}
FixHeaderFile( "precomp.h" );
ProcessFilesInTree( "." );
if ( vout != stdout )
{
fclose( vout ) ;
}
return 0 ;
}
BOOL
GetIncludePath(
CHAR * Path,
BOOL bForce
)
{
FILEINFO fi;
LPSTR p;
LPSTR p2;
DWORD i;
DWORD j;
CHAR s[MAX_PATH*3];
BOOL bBegLine ;
BOOL bFound ;
// Construct the name and open the "sources" file
// Note that the Path string already has a delimiting '\'
sprintf( fi.fname, "%s%s", Path, "sources" ) ;
if ( ! (bFound = MapInputFile( & fi )) )
{
if ( ! bForce )
return FALSE ;
}
else
{
fprintf( vout, "GetIncludePath: processing sources file %s\n", fi.fname );
}
// Allocate a new path string block
if ( ! PushIpath() )
{
fprintf( stderr, "GetIncludePath: out of memory for path storage\n" );
UnMapInputFile( &fi );
return FALSE ;
}
s[0] = 0 ;
if ( bFound )
{
p = fi.fptr;
bBegLine = TRUE ;
while (p && *p)
{
if ( p[0] == 0xd && p[1] == 0xa )
{
bBegLine = TRUE ;
p++ ;
}
else
{
if ( bBegLine && strncmp(p,"INCLUDES",8) == 0 )
{
p+=9;
i=0;
while (*p != '\n')
{
s[i++] = *p++;
}
s[i] = '\0';
break;
}
bBegLine = FALSE ;
}
p++;
}
// Release the sources file
UnMapInputFile( &fi );
}
// Construct the fixed portion of the path table
strcpy( pIpath->ipath[0], "\\nt\\public\\sdk\\inc" );
strcpy( pIpath->ipath[1], "\\nt\\public\\sdk\\inc\\crt" );
strcpy( pIpath->ipath[2], "." );
// Construct the INCLUDES= portion of the path table
if (s[0])
{
p = p2 = s;
j = 3;
while (*p && *p != '\n') {
if (*p == ';') {
*p = '\0';
strcpy( pIpath->ipath[j++], p2 );
p2 = p + 1;
}
p++;
}
if (*p != ';') {
*(p-1) = '\0';
strcpy( pIpath->ipath[j++], p2 );
}
pIpath->cipath = j;
}
return TRUE ;
}
DWORD
FindHeaderFile(
LPSTR HeaderFileName,
BOOL * pbDuplicate
)
{
DWORD i;
WIN32_FIND_DATA fd;
HANDLE hfind;
CHAR fname[MAX_PATH];
DWORD dwResult = BAD_FILE ;
ATOM atFile ;
#define MAX_HEADER_FILES 10000
static ATOM HeaderFileAtoms [MAX_HEADER_FILES] ;
static DWORD HeaderFilePaths [MAX_HEADER_FILES] ;
static INT cMaxHeaderFile = 0 ;
*pbDuplicate = FALSE ;
if ( bIgnoreDups && (atFile = FindAtom( HeaderFileName) ) )
{
for ( i = 0 ;
i < cMaxHeaderFile && HeaderFileAtoms[i] != atFile ;
i++ ) ;
if ( i < cMaxHeaderFile )
{
*pbDuplicate = TRUE ;
return HeaderFilePaths[i] ;
}
}
for (i=0; i< pIpath->cipath; i++)
{
sprintf( fname, "%s\\%s", pIpath->ipath[i], HeaderFileName );
hfind = FindFirstFile( fname, &fd );
if (hfind != INVALID_HANDLE_VALUE)
{
FindClose( hfind );
dwResult = i;
break ;
}
}
if ( dwResult != BAD_FILE
&& bIgnoreDups
&& cMaxHeaderFile < MAX_HEADER_FILES )
{
HeaderFileAtoms[ cMaxHeaderFile ] = AddAtom( HeaderFileName ) ;
HeaderFilePaths[ cMaxHeaderFile ] = dwResult ;
if ( HeaderFileAtoms[ cMaxHeaderFile ] )
cMaxHeaderFile++ ;
}
return dwResult ;
}
VOID
FixHeaderFile(
LPSTR HeaderFileName
)
{
FILEINFO fi;
LPSTR p;
LPSTR p2;
LPSTR p3;
DWORD i;
CHAR fname[MAX_PATH];
CHAR fname2[MAX_PATH];
BOOL bQuote ;
BOOL bDuplicate ;
// Find the file, but ignore the "duplicate" flag,
// since we already know this file needs to be fixed.
i = FindHeaderFile( HeaderFileName, & bDuplicate );
if (i == BAD_FILE)
{
fprintf( vout, "FixHeader: unknown header file %s\n", HeaderFileName );
return;
}
sprintf( fname, "%s\\%s", pIpath->ipath[i], HeaderFileName );
_fullpath( fname2, fname, sizeof(fname2) );
if ( bDebug )
{
fprintf( vout, "FixHeader: processing header: %s\n", fname2 );
}
if ( ! CheckOutSourceFile( fname2 ) )
{
fprintf( stderr, "FixHeader: WARNING -- skipping [%s]\n", fname2 );
return ;
}
strcpy( fi.fname, fname2 );
if ( ! MapOutputFile( &fi, 0 ) )
{
fprintf( stderr, "FixHeader: WARNING -- failed to open and map [%s]\n",
fname2 );
return ;
}
p = fi.fptr;
while (p && *p)
{
if ( p[0] == '/' && p[1] == '/' )
{
for ( ; p[0] && p[0] != '\r' ; p++ ) ;
if ( ! p[0] )
break ;
}
else
if ( p[0] == '/' && p[1] == '*' )
{
for ( ; p[0] && (p[0] != '*' || p[1] != '/') ; p++ ) ;
if ( ! p[0] )
break ;
p++ ;
}
else
if (*p == '#') {
if ( p2 = ScanForHashInclude( p ) )
{
p = p2 + 1 ;
for ( i = 0 ; *p != '>' && *p != '\"' ; )
{
fname[i++] = *p++;
}
bQuote = *p == '\"' ;
p3 = p ;
fname[i] = '\0';
i = FindHeaderFile( fname, & bDuplicate );
if (i == BAD_FILE) {
fprintf( vout, "FixHeader: unknown header file [%s] in header [%s]\n",
fname, HeaderFileName );
} else
if ( i > 1 )
{
if ( ! bQuote )
{
DisplayDelta( HeaderFileName, fname, '\"' ) ;
if ( ! bDebug )
{
*p3 = *p2 = '\"';
fi.bModified = TRUE ;
}
}
if ( ! bDuplicate )
{
FixHeaderFile( fname );
}
}
}
}
p++;
}
UnMapOutputFile( & fi );
return;
}
VOID
ChangeSourceFile(
LPSTR SourceFileName
)
{
LPSTR p;
LPSTR p2;
LPSTR p3;
FILEINFO fi;
DWORD i;
CHAR fname[MAX_PATH];
BOOL bQuote ;
BOOL bDuplicate ;
if ( ! CheckOutSourceFile( SourceFileName ) )
{
fprintf( stderr, "ChangeSource: WARNING -- skipping [%s]\n",
SourceFileName );
return ;
}
strcpy( fi.fname, SourceFileName );
if ( ! MapOutputFile( &fi, 0 ) )
{
fprintf( stderr, "ChangeSource: WARNING -- failed to open and map: [%s]\n",
SourceFileName ) ;
return ;
}
fprintf( vout, "Checking: [%s]\n", SourceFileName ) ;
p = fi.fptr;
while (p && *p)
{
if ( p[0] == '/' && p[1] == '/' )
{
for ( ; p[0] && p[0] != '\r' ; p++ ) ;
if ( ! p[0] )
break ;
}
else
if ( p[0] == '/' && p[1] == '*' )
{
for ( ; p[0] && (p[0] != '*' || p[1] != '/') ; p++ ) ;
if ( ! p[0] )
break ;
p++ ;
}
else
if (*p == '#') {
if ( p2 = ScanForHashInclude( p ) )
{
p = p2 + 1 ;
for ( i = 0 ; *p != '>' && *p != '\"' ; )
{
fname[i++] = *p++;
}
bQuote = *p == '\"' ;
p3 = p ;
fname[i] = '\0';
i = FindHeaderFile( fname, & bDuplicate );
if (i == BAD_FILE) {
fprintf( vout, "ChangeSource: unknown header file [%s] in source [%s]\n",
fname, SourceFileName );
} else
if ( i > 1 )
{
if ( ! bQuote )
{
DisplayDelta( SourceFileName, fname, '\"' ) ;
if ( ! bDebug )
{
*p3 = *p2 = '\"';
fi.bModified = TRUE ;
}
}
if ( ! bDuplicate && _stricmp(fname,"precomp.h") != 0) {
FixHeaderFile( fname );
}
}
}
}
p++;
}
UnMapOutputFile( &fi );
}
#define MAX_DEPTH 32
VOID
ProcessFilesInTree(
LPSTR RootPath
)
{
LPSTR FilePart;
PUCHAR Prefix = "";
CHAR PathBuffer[ MAX_PATH ];
ULONG Depth;
PCHAR PathTail[ MAX_DEPTH ];
PCHAR FindHandle[ MAX_DEPTH ];
LPWIN32_FIND_DATA FindFileData;
UCHAR FindFileBuffer[ MAX_PATH + sizeof( WIN32_FIND_DATA ) ];
CHAR CurrentImageName[ MAX_PATH ];
BOOL SourcesExists [ MAX_DEPTH ] ;
CHAR SavedPath [ MAX_PATH ] ;
CHAR ch ;
strcpy( PathBuffer, RootPath );
FindFileData = (LPWIN32_FIND_DATA)FindFileBuffer;
Depth = 0;
// There's always a SOURCES file at the topmost level
SourcesExists[Depth] = TRUE ;
while (TRUE) {
startDirectorySearch:
PathTail[ Depth ] = strchr( PathBuffer, '\0' );
if (PathTail[ Depth ] > PathBuffer && PathTail[ Depth ][ -1 ] != '\\') {
*(PathTail[ Depth ])++ = '\\';
}
strcpy( PathTail[ Depth ], "*.*" );
FindHandle[ Depth ] = FindFirstFile( PathBuffer, FindFileData );
if (FindHandle[ Depth ] != INVALID_HANDLE_VALUE) {
do {
if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (strcmp( FindFileData->cFileName, "." ) &&
strcmp( FindFileData->cFileName, ".." ) &&
Depth < MAX_DEPTH &&
bRecurse
) {
sprintf( PathTail[ Depth ], "%s\\", FindFileData->cFileName );
SourcesExists[++Depth] = GetIncludePath( PathBuffer, FALSE ) ;
fprintf( vout, "ProcessTree: processing dir: %s\n",
PathBuffer );
goto startDirectorySearch;
}
goto restartDirectorySearch;
} else
if (!IsValidSourceFile( FindFileData->cFileName )) {
goto restartDirectorySearch;
}
strcpy( PathTail[ Depth ], FindFileData->cFileName );
if (!GetFullPathName( PathBuffer, sizeof( CurrentImageName ), CurrentImageName, &FilePart )) {
fprintf( vout, "ProcessTree: invalid file name: %s (%u)\n",
PathBuffer, GetLastError() );
} else {
ch = *FilePart ;
*FilePart = 0 ;
GetCurrentDirectory( sizeof SavedPath, SavedPath ) ;
SetCurrentDirectory( CurrentImageName ) ;
*FilePart = ch ;
ChangeSourceFile( CurrentImageName );
SetCurrentDirectory( SavedPath ) ;
}
restartDirectorySearch:
;
} while (FindNextFile( FindHandle[ Depth ], FindFileData ));
FindClose( FindHandle[ Depth ] );
if ( SourcesExists[Depth] )
{
PopIpath() ;
}
if (Depth == 0) {
break;
}
Depth--;
goto restartDirectorySearch;
}
}
return;
}
BOOL
IsValidSourceFile(
LPSTR fname
)
{
char ext[20];
_splitpath( fname, NULL, NULL, NULL, ext );
if (_stricmp(ext,".c")==0) {
return TRUE;
} else
if (_stricmp(ext,".cxx")==0) {
return TRUE;
} else
if (_stricmp(ext,".cpp")==0) {
return TRUE;
} else {
return FALSE;
}
}
BOOL
CheckOutSourceFile(
LPSTR fname
)
{
DWORD fa;
if ( bDebug )
return TRUE ;
if ( (fa = GetFileAttributes( fname )) == MAXDWORD )
{
fprintf( stderr, "CheckOut: get file attributes FAILED on [%s] (%u)\n",
fname, GetLastError() );
return FALSE ;
}
if (!(fa & FILE_ATTRIBUTE_READONLY)) {
return TRUE;
}
fa ^= FILE_ATTRIBUTE_READONLY;
if ( ! SetFileAttributes( fname, fa ) )
{
fprintf( stderr, "CheckOut: check out (chmode) FAILED on [%s] (%u)\n",
fname, GetLastError() );
return FALSE ;
}
fprintf( vout, "CheckOut: checking out (chmode) %s\n", fname );
#if 0
CHAR szCmdLine[256];
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD dwExitCode;
CHAR dir[_MAX_DIR];
CHAR name[_MAX_FNAME];
CHAR ext[_MAX_EXT];
if (!(GetFileAttributes( fname ) & FILE_ATTRIBUTE_READONLY)) {
return TRUE;
}
fprintf( vout, "CheckOut: checking out %s\n", fname );
_splitpath( fname, NULL, dir, name, ext );
sprintf( szCmdLine, "out -f %s%s", name, ext );
GetStartupInfo( &si );
if (!CreateProcess( NULL, szCmdLine, NULL, NULL,
FALSE, 0, NULL, dir, &si, &pi )) {
return FALSE;
}
WaitForSingleObject( pi.hProcess, INFINITE );
if (!GetExitCodeProcess( pi.hProcess, &dwExitCode )) {
return FALSE;
}
if (dwExitCode) {
return FALSE;
}
#endif
return TRUE;
}
BOOL
MapInputFile (
PFILEINFO lpfi
)
{
lpfi->bModified = FALSE ;
lpfi->hFile = CreateFile( lpfi->fname,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (lpfi->hFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
lpfi->hMap = CreateFileMapping( lpfi->hFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
if (lpfi->hMap == INVALID_HANDLE_VALUE) {
CloseHandle( lpfi->hFile );
return FALSE;
}
lpfi->fptr = MapViewOfFile( lpfi->hMap, FILE_MAP_READ, 0, 0, 0 );
if (lpfi->fptr == NULL) {
CloseHandle( lpfi->hFile );
CloseHandle( lpfi->hMap );
return FALSE;
}
return TRUE;
}
BOOL
MapOutputFile (
PFILEINFO lpfi,
DWORD fsize
)
{
if ( bDebug )
{
return MapInputFile( lpfi ) ;
}
lpfi->bModified = FALSE ;
lpfi->hFile = CreateFile( lpfi->fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (lpfi->hFile == INVALID_HANDLE_VALUE) {
fsize = GetLastError();
return FALSE;
}
lpfi->hMap = CreateFileMapping( lpfi->hFile,
NULL,
PAGE_READWRITE,
0,
fsize,
NULL
);
if (lpfi->hMap == INVALID_HANDLE_VALUE) {
CloseHandle( lpfi->hFile );
return FALSE;
}
lpfi->fptr = MapViewOfFile( lpfi->hMap, FILE_MAP_WRITE, 0, 0, 0 );
if (lpfi->fptr == NULL) {
CloseHandle( lpfi->hFile );
CloseHandle( lpfi->hMap );
return FALSE;
}
return TRUE;
}
VOID
UnMapInputFile(
PFILEINFO lpfi
)
{
CloseHandle( lpfi->hFile );
CloseHandle( lpfi->hMap );
UnmapViewOfFile( lpfi->fptr );
}
VOID
UnMapOutputFile(
PFILEINFO lpfi
)
{
if ( lpfi->bModified )
{
// File mapper doesn't seem to update file times.
FILETIME fileTime ;
SYSTEMTIME sysTime ;
GetSystemTime( & sysTime ) ;
SystemTimeToFileTime( & sysTime, & fileTime ) ;
SetFileTime( lpfi->hFile, NULL, NULL, & fileTime ) ;
}
CloseHandle( lpfi->hFile );
CloseHandle( lpfi->hMap );
UnmapViewOfFile( lpfi->fptr );
}
//
// Scan for a valid #include statement. This
// eats white space in all possible positions.
// Returns a pointer to the '<' or '"' character
// staring the inclusion file name or NULL if failure.
//
CHAR *
ScanForHashInclude(
CHAR * pch
)
{
if ( *pch != '#' )
return NULL ;
for ( ; *++pch == ' ' ; ) ;
if ( strncmp( pch, "include", 7 ) )
return NULL ;
for ( pch += 7 ; *pch == ' ' ; pch++ ) ;
if ( *pch != '\"' && *pch != '<' )
return NULL ;
return pch ;
}
VOID
DisplayDelta (
CHAR * pchFileName,
CHAR * pchHeaderName,
CHAR chNewMark
)
{
CHAR chOther = chNewMark == '<' ? '>' : '\"' ;
fprintf( vout, "FileDelta: [%s] #include %c%s%c\n",
pchFileName, chNewMark, pchHeaderName, chOther ) ;
}
BOOL
PushIpath ( void )
{
IPATH * pip = malloc( sizeof (IPATH) ) ;
if ( pip == NULL )
return FALSE ;
memset( pip, 0, sizeof (IPATH) ) ;
pip->pIpNext = pIpath ;
pip->cipath = 0 ;
pIpath = pip ;
return TRUE ;
}
BOOL
PopIpath ( void )
{
IPATH * pip = pIpath ;
if ( pip == NULL )
return FALSE ;
pIpath = pip->pIpNext ;
free( pip ) ;
return TRUE ;
}