windows-nt/Source/XPSP1/NT/base/ntsetup/bom/boot/boot.c
2020-09-26 16:20:57 +08:00

754 lines
22 KiB
C

/*
* 10.23.97 Joe Holman Make our 3 boot disks for a product.
* This program needs to do the following:
*
* 1. calculate if the boot files value
* is adequate
* 2. create a list of files that can be used
* to make the boot floppies.
*
* 11.02.98 Joe Holman Modified per new key names.
* 11.19.98 Elliott Munger Made changes to suport 4 bootdisks
*/
#include <stdlib.h>
#include <direct.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <conio.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <process.h>
#include <ctype.h>
#include <windows.h>
#include <time.h>
#include <setupapi.h>
int __cdecl main( int, char ** );
FILE * logFile;
HANDLE hDosnetInf;
CHAR returnBuffer[MAX_PATH];
CHAR returnBuffer2[MAX_PATH];
CHAR szWrite[MAX_PATH];
CHAR szFloppyDump[MAX_PATH];
CHAR szLog[MAX_PATH];
CHAR szReleaseShare[MAX_PATH];
DWORD dwRequiredSize;
CHAR szDosnetPath[MAX_PATH];
CHAR szLayoutPath[MAX_PATH];
CHAR szRenamedFile[MAX_PATH];
CHAR szBootSector[MAX_PATH];
BOOL bHasRenamedFile = FALSE;
BOOL bMakeNECBoot = FALSE;
//
// Macro for rounding up any number (x) to multiple of (n) which
// must be a power of 2. For example, ROUNDUP( 2047, 512 ) would
// yield result of 2048.
//
#define ROUNDUP2( x, n ) (((x) + ((n) - 1 )) & ~((n) - 1 ))
#define _hK 512
#define _1K 1*1024
#define _2K 2*1024
#define _4K 4*1024
#define _8K 8*1024
#define _16K 16*1024
#define _32K 32*1024
#define _64K 64*1024
#define _128K 128*1024
#define _256K 256*1024
// System parition values per cluster size for
// files that go in the ~BT directory.
//
DWORD dw_hK = 0;
DWORD dw_1K = 0;
DWORD dw_2K = 0;
DWORD dw_4K = 0;
DWORD dw_8K = 0;
DWORD dw_16K = 0;
DWORD dw_32K = 0;
DWORD dw_64K = 0;
DWORD dw_128K = 0;
DWORD dw_256K = 0;
void Msg ( const char * szFormat, ... ) {
va_list vaArgs;
va_start ( vaArgs, szFormat );
vprintf ( szFormat, vaArgs );
vfprintf ( logFile, szFormat, vaArgs );
va_end ( vaArgs );
}
void Usage( void ) {
printf ( "Usage: boot logFile dosnet.inf-path output-file-for-dmf flat-uncompressed-share path-for-floppy-files x86orNECbootdisk" );
exit (1);
}
void Header(argv)
char* argv[];
{
time_t t;
Msg ("\n=========== BOOT.EXE =============\n");
Msg ("LogFile : %s\n",argv[1]);
Msg ("DosNet.INF path : %s\n",argv[2]);
Msg ("Output file path : %s\n",argv[3]);
Msg ("Flat uncompressed share: %s\n", argv[4] );
Msg ("Path to put floppy files:%s\n", argv[5] );
Msg ("X86 or NEC Boot sector : %s\n", argv[6] );
time(&t);
Msg ("Time : %s",ctime(&t));
Msg ("================================\n\n");
}
void WriteToFile ( char * fileName, char flopNum ) {
FILE * fHandle;
CHAR Line[MAX_PATH];
CHAR szPath[MAX_PATH];
sprintf ( szPath, "%s\\b%c.txt", szFloppyDump, flopNum );
fHandle = fopen ( szPath, "a" );
if ( fHandle == NULL ) {
Msg ( "ERROR Couldn't open file with fopen: %s\n", szPath );
}
else {
// This denotes that it is the first floppy,
// which needs to have the boot sector put on it.
//
if ( strstr ( fileName, "disk1" ) && flopNum == '0' ) {
if ( bMakeNECBoot ) {
strcpy ( Line, "-bnt35nec98setup\n" );
}
else {
strcpy ( Line, "-bnt35setup\n" );
}
fwrite ( Line, 1, strlen(Line), fHandle );
Msg ( "\nWritingToFile: %s\n%s\n\n", szPath, Line );
}
if ( bHasRenamedFile ) {
sprintf ( Line, "%s=%s\n", fileName, returnBuffer2 );
}
else {
sprintf ( Line, "%s\n" , fileName );
}
fwrite ( Line, 1, strlen(Line), fHandle );
Msg ( "\nWritingToFile: %s\n%s\n\n", szPath, Line );
fclose ( fHandle );
}
}
VOID MakeCompName ( const char * inFile, char * outFile ) {
unsigned i;
unsigned period;
strcpy( outFile, inFile );
for ( period=(unsigned)(-1), i = 0 ; i < strlen(inFile); i++ ) {
if ( inFile[i] == '.' ) {
period = i;
}
}
if ( period == (strlen(inFile)-4) ) {
outFile[strlen(outFile)-1] = '_';
}
else if ( period == (unsigned)(-1)) {
strcat ( outFile, "._");
}
else {
strcat ( outFile, "_");
}
}
void ChangeFileNameToCompressNameIfNeeded ( char * fileName ) {
HANDLE hLayoutInf;
// See if the file is going to come over as compressed or not.
// If so, change it's name so we can process it.
//
// Special case for files not stored in the INF.
//
if ( strstr ( fileName, "disk1" ) ||
strstr ( fileName, "setupldr.bin" ) ||
strstr ( fileName, "usetup.exe" ) ) {
goto no_processing;
}
// Open layout.inf to find out if the file is to be compressed or not.
//
hLayoutInf = SetupOpenInfFile ( szLayoutPath, NULL, INF_STYLE_WIN4, NULL );
if ( hLayoutInf == INVALID_HANDLE_VALUE ) {
Msg ( "ERROR: ChangeFileNameToCompressNameIfNeeded could not open INF: %s\n", szLayoutPath );
}
else {
BOOL b;
DWORD requiredSize;
INFCONTEXT ic;
CHAR returnBuffer[MAX_PATH];
b = SetupFindFirstLine ( hLayoutInf,
(LPSTR) "SourceDisksFiles",
(LPSTR) fileName,
&ic );
if ( !b ) {
// If we get an error, perhaps the file is in the .x86 section.
//
b = SetupFindFirstLine (hLayoutInf,
(LPSTR) "SourceDisksFiles.x86",
(LPSTR) fileName,
&ic );
if ( !b ) {
Msg ( "ERROR: CopyTheFile SetupFindFirstLine couldn't find file in section: gle = %x, >>>%s<<<\n",
GetLastError(), fileName );
}
else {
goto continue_here;
}
}
else {
continue_here:;
// Look at the 7th field.
//
b = SetupGetStringField ( &ic,
7,
(LPSTR) returnBuffer,
sizeof ( returnBuffer ),
&dwRequiredSize );
if ( !b ) {
Msg ( "ERROR: CopyTheFile SetupGetStringField gle = %ld\n", GetLastError());
}
else {
char * p;
Msg ( "++++ returnBuffer = %s\n", returnBuffer );
// Get to the character that determines if we compress or not.
//
p = returnBuffer;
if ( *p != '_' ) {
CHAR commandBuffer[MAX_PATH];
CHAR szTmp[MAX_PATH];
// Since we are going to be using a compressed filename,
// turn the uncompressed filename into a compressed filename.
//
MakeCompName ( fileName, szTmp );
strcpy ( fileName, szTmp );
Msg ( "using compressed filename, so now it is: %s\n", fileName );
}
else {
Msg ( "leaving filename alone, still: %s\n", fileName );
}
}
}
SetupCloseInfFile ( hLayoutInf );
}
no_processing:;
}
void AddInSize ( char * fileName ) {
CHAR szPath[MAX_PATH];
HANDLE h;
WIN32_FIND_DATA wfd;
sprintf ( szPath, "%s\\%s", szReleaseShare, fileName );
Msg ( "\n+++ AddInSize for: %s +++\n", szPath );
h = FindFirstFile ( szPath, &wfd );
if ( h == INVALID_HANDLE_VALUE ) {
Msg ( "ERROR: FindFirstFile on %s, gle = %ld\n", szPath, GetLastError() );
}
else {
dw_hK += ROUNDUP2 ( wfd.nFileSizeLow, 512 );
dw_1K += ROUNDUP2 ( wfd.nFileSizeLow, _1K );
dw_2K += ROUNDUP2 ( wfd.nFileSizeLow, _2K );
dw_4K += ROUNDUP2 ( wfd.nFileSizeLow, _4K );
dw_8K += ROUNDUP2 ( wfd.nFileSizeLow, _8K );
dw_16K += ROUNDUP2 ( wfd.nFileSizeLow, _16K );
dw_32K += ROUNDUP2 ( wfd.nFileSizeLow, _32K );
dw_64K += ROUNDUP2 ( wfd.nFileSizeLow, _64K );
dw_128K += ROUNDUP2 ( wfd.nFileSizeLow, _128K );
dw_256K += ROUNDUP2 ( wfd.nFileSizeLow, _256K );
/*
Msg ( "dw_hK = %ld\n", dw_hK );
Msg ( "dw_1K = %ld\n", dw_1K );
Msg ( "dw_2K = %ld\n", dw_2K );
Msg ( "dw_4K = %ld\n", dw_4K );
Msg ( "dw_8K = %ld\n", dw_8K );
Msg ( "dw_16K = %ld\n", dw_16K );
Msg ( "dw_32K = %ld\n", dw_32K );
Msg ( "dw_64K = %ld\n", dw_64K );
Msg ( "dw_128K = %ld\n", dw_128K );
Msg ( "dw_256K = %ld\n", dw_256K );
*/
FindClose ( h );
}
}
void CopyTheFile ( CHAR * fileName, CHAR flopNum ) {
CHAR szPath1[MAX_PATH];
CHAR szPath2[MAX_PATH];
BOOL b;
Msg ( "CopyTheFile: %s\n", fileName );
// Copy the file.
//
sprintf ( szPath1, "%s\\%s", szReleaseShare, fileName );
sprintf ( szPath2, "%s\\%s", szFloppyDump, fileName );
b = CopyFile ( szPath1, szPath2, FALSE );
if ( !b ) {
Msg ( "ERROR: CopyFile failed, gle = %ld, >>>%s<<< >>>%s<<<\n",
GetLastError(), szPath1, szPath2 );
}
else {
Msg ( "CopyFile: %s %s [ok]\n", szPath1, szPath2 );
SetFileAttributes ( szPath2, FILE_ATTRIBUTE_NORMAL );
}
// Write the name of the file to B?.txt file in the specified directory.
//
WriteToFile ( fileName, flopNum );
}
void GetFloppy ( char Floppy ) {
BOOL b;
INFCONTEXT ic;
char szSection[MAX_PATH];
sprintf ( szSection, "%s%c", "FloppyFiles.", Floppy );
Msg ( "\nGetting for section: %s\n\n", szSection );
// Get the first line in the section, ie FloppyFiles.N.
// Note: Be sure to look for files that maybe renamed:
//
// d1,disk1,disk101
// disk1=disk101 for the output file.
//
b = SetupFindFirstLine ( hDosnetInf,
szSection,
NULL,
&ic );
if ( !b ) {
Msg ( "ERROR: SetupFindFirstLine not found in %s\n", szSection );
}
else {
// Get the 2nd field's filename, such as in d1,disk1,disk101
// would be disk1.
//
b = SetupGetStringField ( &ic,
2,
(LPSTR) &returnBuffer,
sizeof ( returnBuffer ),
&dwRequiredSize );
if ( !b ) {
Msg ( "ERROR: SetupGetStringField gle = %ld\n", GetLastError());
}
// See if we need to compress this file and
// add in the size for the ~bt directory.
//
ChangeFileNameToCompressNameIfNeeded ( returnBuffer );
AddInSize ( returnBuffer );
// Get the 3rd field's filename, such as in d1,disk1,disk101
// would be disk101.
// This is the case where we need to stick disk1=disk101 for
// the output file for disk imaging.
//
// Note: we don't check for errors here because 3rd field
// because this renamed file is optional.
//
b = SetupGetStringField ( &ic,
3,
(LPSTR) &returnBuffer2,
sizeof ( returnBuffer2 ),
&dwRequiredSize );
// Note - not checking for errors here.
//
if ( b ) {
bHasRenamedFile = TRUE;
}
else {
bHasRenamedFile = FALSE;
}
// Copy the file to the specified directory.
//
CopyTheFile ( returnBuffer, Floppy );
while ( 1 ) {
// Get the next line in the section.
//
b = SetupFindNextLine ( &ic,
&ic );
if ( !b ) {
// Denotes that there is NOT another line.
//
Msg ( "\n" );
break;
}
else {
// Get the 2nd field's filename,
// such as in d1,disk1,disk101
// would be disk1.
//
b = SetupGetStringField ( &ic,
2,
(LPSTR) &returnBuffer,
sizeof ( returnBuffer ),
&dwRequiredSize );
if ( !b ) {
Msg ( "ERROR: SetupGetStringField gle = %ld\n", GetLastError());
break;
}
//Msg ( "returnBuffer = %s\n", returnBuffer );
ChangeFileNameToCompressNameIfNeeded ( returnBuffer );
AddInSize ( returnBuffer );
// Get the 3rd field's filename, such as in
// d1,disk1,disk101
// would be disk101.
// This is the case where we need to stick
// disk1=disk101 for
// the output file for disk imaging.
//
// Note: we don't check for errors here because 3rd field
// because this renamed file is optional.
//
b = SetupGetStringField ( &ic,
3,
(LPSTR) &returnBuffer2,
sizeof ( returnBuffer2 ),
&dwRequiredSize );
// Note - not checking for errors here.
//
if ( b ) {
bHasRenamedFile = TRUE;
}
else {
bHasRenamedFile = FALSE;
}
// Copy the file to the specified directory.
//
CopyTheFile ( returnBuffer, Floppy );
}
}
}
}
DWORD Get2ndSize ( char * key ) {
CHAR returnedString[MAX_PATH];
#define OHPROBLEM "OH OH"
DWORD dwSize = 666;
char * p;
GetPrivateProfileString ( "DiskSpaceRequirements",
key,
OHPROBLEM,
returnedString,
MAX_PATH,
szDosnetPath );
if ( strncmp ( returnedString, OHPROBLEM, sizeof ( OHPROBLEM ) ) == 0 ) {
Msg ( "ERROR: section >>>%s<<< not found.\n", key );
}
//Msg ( ">>> %s\n", returnedString );
// Find the ',' which denotes the ~BT data.
//
p = strstr ( returnedString, "," );
if ( !p ) {
Msg ( "ERROR: returnedString has no ',' in it: %s\n", returnedString );
dwSize = 0;
}
else {
++p; // point to the number, not the ','
dwSize = atoi ( p );
//Msg ( ">+BT dwSize = %ld, p = %s\n", dwSize, p );
}
return (dwSize);
}
DWORD GetBT ( DWORD ClusterSize ) {
switch ( ClusterSize ) {
case _hK :
return Get2ndSize ( "TempDirSpace512" );
break;
case _1K :
return Get2ndSize ( "TempDirSpace1K" );
break;
case _2K :
return Get2ndSize ( "TempDirSpace2K" );
break;
case _4K :
return Get2ndSize ( "TempDirSpace4K" );
break;
case _8K :
return Get2ndSize ( "TempDirSpace8K" );
break;
case _16K :
return Get2ndSize ( "TempDirSpace16K" );
break;
case _32K :
return Get2ndSize ( "TempDirSpace32K" );
break;
case _64K :
return Get2ndSize ( "TempDirSpace64K" );
break;
case _128K :
return Get2ndSize ( "TempDirSpace128K" );
break;
case _256K :
return Get2ndSize ( "TempDirSpace256K" );
break;
default :
Msg ( "ERROR: ClusterSize not known: %ld\n", ClusterSize );
break;
}
return 0;
}
void VerifyTotalSizeIsAdaquate ( void ) {
// Make sure that the total size we need is specified in dosnet.inf.
//
Msg ( "\n\nVerifyTotalSizeIsAdaquate...\n" );
// Dosnet.inf's [SpaceRequirements] cluster fields should look like:
//
// 512 = xxxxxx, yyyyyy where x is for the ~LS files and
// where y is for the ~BT files.
//
#define FUDGE 1*1024*1024 // to make sure we have enough for dir entries in FAT.
if ( dw_hK > GetBT ( _hK ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 512 ~BT too small, %ld, use: %ld\n", GetBT ( _hK ), dw_hK+FUDGE );
}
if ( dw_1K > GetBT ( _1K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 1K ~BT too small, %ld, use: %ld\n", GetBT ( _1K ), dw_1K+FUDGE );
}
if ( dw_2K > GetBT ( _2K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 2K ~BT too small, %ld, use: %ld\n", GetBT ( _2K ), dw_2K+FUDGE );
}
if ( dw_4K > GetBT ( _4K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 4K ~BT too small, %ld, use: %ld\n", GetBT ( _4K ), dw_4K+FUDGE );
}
if ( dw_8K > GetBT ( _8K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 8K ~BT too small, %ld, use: %ld\n", GetBT ( _8K ), dw_8K+FUDGE );
}
if ( dw_16K > GetBT ( _16K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 16K ~BT too small, %ld, use: %ld\n", GetBT ( _16K ), dw_16K+FUDGE );
}
if ( dw_32K > GetBT ( _32K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 32K ~BT too small, %ld, use: %ld\n", GetBT ( _32K ), dw_32K+FUDGE );
}
if ( dw_64K > GetBT ( _64K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 64K ~BT too small, %ld, use: %ld\n", GetBT ( _64K ), dw_64K+FUDGE );
}
if ( dw_128K > GetBT ( _128K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 128K ~BT too small, %ld, use: %ld\n", GetBT ( _128K ), dw_128K+FUDGE );
}
if ( dw_256K > GetBT ( _256K ) ) {
Msg ( "matth ERROR: Dosnet.inf's [DiskSpaceRequirements]'s 256K ~BT too small, %ld, use: %ld\n", GetBT ( _256K ), dw_256K+FUDGE );
}
}
void MyDeleteFile ( char Num ) {
BOOL b;
CHAR szPath[MAX_PATH];
sprintf ( szPath, "%s\\b%c.txt", szFloppyDump, Num );
Msg ( "Deleting: %s\n", szPath );
b = DeleteFile ( szPath );
if ( !b ) {
if ( GetLastError() != ERROR_FILE_NOT_FOUND ) {
Msg ( "ERROR: DeleteFile, gle = %ld, %s\n", GetLastError(), szPath );
}
}
}
__cdecl main ( int argc, char * argv[] ) {
if ( argc != 7) {
Usage();
exit(1);
}
if ((logFile=fopen(argv[1],"a"))==NULL) {
printf("ERROR Couldn't open logFile: %s\n",argv[1]);
return(1);
}
Header(argv);
Msg ( "%s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6] );
// Copy paths into appropriate string variables.
//
strcpy ( szLog, argv[1] );
Msg ( "szLog = %s\n", szLog );
strcpy ( szDosnetPath, argv[2] );
Msg ( "szDosnetPath = %s\n", szDosnetPath );
strcpy ( szReleaseShare, argv[4] );
Msg ( "szReleaseShare = %s\n", szReleaseShare );
sprintf ( szLayoutPath, "%s\\%s", argv[4], "layout.inf" );
Msg ( "szLayoutPath = %s\n", szLayoutPath );
strcpy ( szFloppyDump, argv[5] );
Msg ( "szFloppyDump = %s\n", szFloppyDump );
strcpy ( szBootSector, argv[6] );
Msg ( "szBootSector = %s\n", szBootSector );
if ( strstr ( szBootSector, "NEC" ) ) {
bMakeNECBoot = TRUE;
Msg ( "Making this boot floppy #1 NEC98 bootable...\n" );
}
//
//
hDosnetInf = SetupOpenInfFile ( szDosnetPath, NULL, INF_STYLE_WIN4, NULL );
if ( hDosnetInf == INVALID_HANDLE_VALUE ) {
Msg ( "ERROR: boot.exe - could not open INF: %s\n", szDosnetPath );
}
else {
CHAR szPath[MAX_PATH];
BOOL b;
// Delete the files that hold the file list.
//
MyDeleteFile ( '0' );
MyDeleteFile ( '1' );
MyDeleteFile ( '2' );
MyDeleteFile ( '3' );
GetFloppy ( '0' );
GetFloppy ( '1' );
GetFloppy ( '2' );
GetFloppy ( '3' );
SetupCloseInfFile ( hDosnetInf );
VerifyTotalSizeIsAdaquate ();
}
}