1221 lines
30 KiB
C
1221 lines
30 KiB
C
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (c) 1999 Microsoft Corporation
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// File Name:
|
||
|
// makebt32.c
|
||
|
//
|
||
|
// Description:
|
||
|
// This program copies the images of the 4 Windows NT setup disks to
|
||
|
// floppy disk so the user can boot their system with them.
|
||
|
//
|
||
|
// All characters and strings are wide (UNICODE). This file needs to be
|
||
|
// compiled with UNICODE and _UNICODE defined.
|
||
|
//
|
||
|
// Assumptions:
|
||
|
// This program will only run on NT 3.51 or later. This is a result of
|
||
|
// the CreateFile function call. It is not available on DOS, Windows 3.1
|
||
|
// or Windows 9x.
|
||
|
//
|
||
|
// The floppy disk images are in the current dir and named CDBOOT1.IMG,
|
||
|
// CDBOOT2.IMG, CDBOOT3.IMG and CDBOOT4.IMG.
|
||
|
//
|
||
|
// Please note that there are a lot of places where I call exit() without
|
||
|
// freeing memory for strings I have allocated. This version of the
|
||
|
// program only runs on NT so when the process exits it frees all its
|
||
|
// memory so it is not a concern that I may not call free() on some memory.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <setupapi.h>
|
||
|
#include <winioctl.h>
|
||
|
#include <conio.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "resource.h"
|
||
|
|
||
|
//
|
||
|
// Constants
|
||
|
//
|
||
|
#define MAKEBOOT_MAX_STRING_LEN 1024
|
||
|
#define BYTES_PER_SECTOR 512
|
||
|
#define SECTORS_PER_TRACK 18
|
||
|
#define TRACK_SIZE SECTORS_PER_TRACK * BYTES_PER_SECTOR
|
||
|
#define TRACKS_ON_DISK 80 * 2 // * 2 because it is double-sided
|
||
|
|
||
|
#define MAX_DISK_LABEL_LENGTH 256
|
||
|
#define MAX_INILINE_LENGTH 1023
|
||
|
|
||
|
#define ENTER_KEY 13
|
||
|
#define ESC_KEY 27
|
||
|
|
||
|
#define NT_IMAGE_1_NAME L"CDBOOT1.IMG"
|
||
|
#define NT_IMAGE_2_NAME L"CDBOOT2.IMG"
|
||
|
#define NT_IMAGE_3_NAME L"CDBOOT3.IMG"
|
||
|
#define NT_IMAGE_4_NAME L"CDBOOT4.IMG"
|
||
|
#define NT_IMAGE_5_NAME L"CDBOOT5.IMG"
|
||
|
#define NT_IMAGE_6_NAME L"CDBOOT6.IMG"
|
||
|
|
||
|
#define NUMBER_OF_ASCII_WHEEL_SYMBOLS 4
|
||
|
|
||
|
const WCHAR rgAsciiWheel[NUMBER_OF_ASCII_WHEEL_SYMBOLS] = { '|', '/', '-', '\\' };
|
||
|
|
||
|
//
|
||
|
// Function prototypes
|
||
|
//
|
||
|
BOOL WriteImageToFloppy( WCHAR *szFileName, WCHAR *DrivePath );
|
||
|
VOID PrintErrorMessage( VOID );
|
||
|
VOID PrintErrorWrongDriveType( UINT iDriveType );
|
||
|
BOOL IsDriveLargeEnough( WCHAR *DrivePath );
|
||
|
VOID FreeStrings( VOID );
|
||
|
VOID LoadStrings( VOID );
|
||
|
INT DoImageFilesExist( VOID ) ;
|
||
|
VOID CleanUp( HANDLE *hFloppyDrive, HANDLE *hFloppyImage );
|
||
|
BOOL DoesUserWantToTryCopyAgain( VOID );
|
||
|
LPWSTR MyLoadString( UINT StringId );
|
||
|
VOID print( WCHAR *szFirstString, ... );
|
||
|
BOOL DoesFileExist( LPWSTR lpFileName );
|
||
|
VOID PressAnyKeyToContinue( VOID );
|
||
|
void SetFarEastThread();
|
||
|
void ConsolePrint( WCHAR *szFirstString, ... );
|
||
|
//
|
||
|
// Global Strings
|
||
|
//
|
||
|
WCHAR *StrOutOfMemory = NULL;
|
||
|
WCHAR *StrComplete = NULL;
|
||
|
WCHAR *StrNtVersionName = NULL;
|
||
|
WCHAR *StrCanNotFindFile = NULL;
|
||
|
WCHAR *StrDiskLabel1 = NULL;
|
||
|
WCHAR *StrDiskLabel2 = NULL;
|
||
|
WCHAR *StrDiskLabel3 = NULL;
|
||
|
WCHAR *StrDiskLabel4 = NULL;
|
||
|
WCHAR *StrDiskLabel5 = NULL;
|
||
|
WCHAR *StrDiskLabel6 = NULL;
|
||
|
|
||
|
WCHAR *StrStars = NULL;
|
||
|
WCHAR *StrExplanationLine1 = NULL;
|
||
|
WCHAR *StrExplanationLine2 = NULL;
|
||
|
WCHAR *StrExplanationLine3 = NULL;
|
||
|
WCHAR *StrExplanationLine4 = NULL;
|
||
|
WCHAR *StrInsertFirstDiskLine1 = NULL;
|
||
|
WCHAR *StrInsertFirstDiskLine2 = NULL;
|
||
|
WCHAR *StrInsertAnotherDiskLine1 = NULL;
|
||
|
WCHAR *StrInsertAnotherDiskLine2 = NULL;
|
||
|
WCHAR *StrPressAnyKeyWhenReady = NULL;
|
||
|
WCHAR *StrCompletedSuccessfully = NULL;
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: wmain
|
||
|
//
|
||
|
// Purpose: Instructs user to insert floppy disks to be copied and performs
|
||
|
// the copy.
|
||
|
//
|
||
|
// Arguments: int argc - standard program argument, count of the command line args
|
||
|
// char *argv[] - standard program argument, the 2nd argument is the
|
||
|
// floppy drive to copy the images to.
|
||
|
//
|
||
|
// Returns: INT - zero on successful program completion
|
||
|
// - non-zero on unsuccessful program completion, program
|
||
|
// terminated because of an error
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
INT __cdecl
|
||
|
wmain( INT argc, WCHAR *argv[] )
|
||
|
{
|
||
|
|
||
|
WCHAR *szOsName;
|
||
|
WCHAR DriveLetter;
|
||
|
WCHAR Drive[10];
|
||
|
WCHAR DrivePath[10];
|
||
|
UINT iDriveType;
|
||
|
BOOL bTryAgain;
|
||
|
|
||
|
szOsName = _wgetenv( L"OS" );
|
||
|
|
||
|
//
|
||
|
// Make sure we are on NT.
|
||
|
//
|
||
|
if( ( szOsName == NULL ) || ( _wcsicmp( szOsName, L"Windows_NT" ) != 0 ) )
|
||
|
{
|
||
|
|
||
|
// ******
|
||
|
// This string cannot be localized because if we are not on NT then
|
||
|
// we don't have wide chars.
|
||
|
//
|
||
|
printf( "This program only runs on Windows NT, Windows 2000 and Windows XP.\n" );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
SetFarEastThread();
|
||
|
|
||
|
//
|
||
|
// Load all of the strings from the resource file
|
||
|
//
|
||
|
LoadStrings();
|
||
|
|
||
|
//
|
||
|
// Don't allow the system to do any pop-ups. We will handle all
|
||
|
// error messages
|
||
|
//
|
||
|
SetErrorMode( SEM_FAILCRITICALERRORS );
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrStars );
|
||
|
|
||
|
print( StrExplanationLine1 );
|
||
|
|
||
|
print( StrExplanationLine2, StrNtVersionName );
|
||
|
|
||
|
print( StrExplanationLine3 );
|
||
|
print( StrExplanationLine4 );
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
//
|
||
|
// If they didn't specified the floppy drive on the command line then
|
||
|
// prompt them for it.
|
||
|
//
|
||
|
if( argc == 1 )
|
||
|
{
|
||
|
|
||
|
WCHAR *StrSpecifyFloppyDrive = MyLoadString( IDS_SPECIFY_FLOPPY_DRIVE );
|
||
|
|
||
|
ConsolePrint( L"%s", StrSpecifyFloppyDrive );
|
||
|
|
||
|
DriveLetter = (WCHAR)_getche();
|
||
|
|
||
|
ConsolePrint( L"\n\n" );
|
||
|
|
||
|
free( StrSpecifyFloppyDrive );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
DriveLetter = argv[1][0];
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure the character they entered is a possible drive letter
|
||
|
//
|
||
|
if( ! isalpha( DriveLetter ) )
|
||
|
{
|
||
|
|
||
|
WCHAR *StrInvalidDriveLetter = MyLoadString( IDS_INVALID_DRIVE_LETTER );
|
||
|
|
||
|
ConsolePrint( L"%s\n", StrInvalidDriveLetter );
|
||
|
|
||
|
free( StrInvalidDriveLetter );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure all the image files are in the current directory.
|
||
|
//
|
||
|
if( ! DoImageFilesExist() )
|
||
|
{
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make the char DriveLetter into a string
|
||
|
//
|
||
|
Drive[0] = DriveLetter;
|
||
|
Drive[1] = L'\0';
|
||
|
|
||
|
//
|
||
|
// Build the drive path. For example the a: drive looks like \\.\a:
|
||
|
//
|
||
|
swprintf( DrivePath, L"\\\\.\\%c:", DriveLetter );
|
||
|
|
||
|
//
|
||
|
// Make sure the drive is a floppy drive
|
||
|
//
|
||
|
iDriveType = GetDriveType( wcscat( Drive, L":\\" ) );
|
||
|
|
||
|
if( iDriveType != DRIVE_REMOVABLE )
|
||
|
{
|
||
|
|
||
|
PrintErrorWrongDriveType( iDriveType );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure the drive can hold at least 1.44 MB
|
||
|
//
|
||
|
if( ! IsDriveLargeEnough( DrivePath ) )
|
||
|
{
|
||
|
|
||
|
WCHAR *Str144NotSupported = MyLoadString( IDS_144_NOT_SUPPORTED );
|
||
|
|
||
|
ConsolePrint( L"%s\n", Str144NotSupported );
|
||
|
|
||
|
free( Str144NotSupported );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
print( StrInsertFirstDiskLine1, DriveLetter );
|
||
|
print( StrInsertFirstDiskLine2, StrDiskLabel1 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_1_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrInsertAnotherDiskLine1, DriveLetter );
|
||
|
print( StrInsertAnotherDiskLine2, StrDiskLabel2 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_2_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrInsertAnotherDiskLine1, DriveLetter );
|
||
|
print( StrInsertAnotherDiskLine2, StrDiskLabel3 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_3_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrInsertAnotherDiskLine1, DriveLetter );
|
||
|
print( StrInsertAnotherDiskLine2, StrDiskLabel4 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_4_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrInsertAnotherDiskLine1, DriveLetter );
|
||
|
print( StrInsertAnotherDiskLine2, StrDiskLabel5 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_5_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrInsertAnotherDiskLine1, DriveLetter );
|
||
|
print( StrInsertAnotherDiskLine2, StrDiskLabel6 );
|
||
|
|
||
|
PressAnyKeyToContinue();
|
||
|
|
||
|
while( ! WriteImageToFloppy( NT_IMAGE_6_NAME, DrivePath ) )
|
||
|
{
|
||
|
|
||
|
bTryAgain = DoesUserWantToTryCopyAgain();
|
||
|
|
||
|
if( ! bTryAgain )
|
||
|
{
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
print( L"" );
|
||
|
|
||
|
print( StrCompletedSuccessfully );
|
||
|
|
||
|
print( StrStars );
|
||
|
|
||
|
FreeStrings();
|
||
|
|
||
|
return( 0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: WriteImageToFloppy
|
||
|
//
|
||
|
// Purpose: Writes an image file to a floppy disk. Handles all error
|
||
|
// reporting to the user.
|
||
|
//
|
||
|
// Arguments: char *szFileName - filename to write to the floppy
|
||
|
// char *DrivePath - drive path of the floppy to write to, it is of
|
||
|
// the form \\.\x where x is the drive letter
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if image written to floppy properly
|
||
|
// FALSE if there were errors
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WriteImageToFloppy( WCHAR *szFileName, WCHAR *DrivePath )
|
||
|
{
|
||
|
|
||
|
INT iCurrentTrack;
|
||
|
INT cBytesRead = 0;
|
||
|
INT cBytesWritten = 0;
|
||
|
INT iPercentComplete = 0;
|
||
|
INT iWheelPosition = 0;
|
||
|
HANDLE hFloppyImage = NULL;
|
||
|
HANDLE hFloppyDrive = NULL;
|
||
|
char TrackBuffer[TRACK_SIZE];
|
||
|
|
||
|
hFloppyImage = CreateFile( szFileName,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
||
|
NULL );
|
||
|
|
||
|
if( hFloppyImage == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
|
||
|
PrintErrorMessage();
|
||
|
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
hFloppyDrive = CreateFile( DrivePath,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
||
|
NULL );
|
||
|
|
||
|
if( hFloppyDrive == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
|
||
|
PrintErrorMessage();
|
||
|
|
||
|
CleanUp( &hFloppyDrive, &hFloppyImage );
|
||
|
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
for( iCurrentTrack = 0; iCurrentTrack < TRACKS_ON_DISK; iCurrentTrack++ )
|
||
|
{
|
||
|
if( ! ReadFile( hFloppyImage, TrackBuffer, TRACK_SIZE, &cBytesRead, NULL ) )
|
||
|
{
|
||
|
|
||
|
PrintErrorMessage();
|
||
|
|
||
|
CleanUp( &hFloppyDrive, &hFloppyImage );
|
||
|
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
if( ! WriteFile( hFloppyDrive, TrackBuffer, TRACK_SIZE, &cBytesWritten, NULL ) )
|
||
|
{
|
||
|
|
||
|
PrintErrorMessage();
|
||
|
|
||
|
CleanUp( &hFloppyDrive, &hFloppyImage );
|
||
|
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
iPercentComplete = (int) ( ( (double) (iCurrentTrack) / (double) (TRACKS_ON_DISK) ) * 100.0 );
|
||
|
|
||
|
ConsolePrint( L"%c %3d%% %s.\r",
|
||
|
rgAsciiWheel[iWheelPosition],
|
||
|
iPercentComplete,
|
||
|
StrComplete );
|
||
|
|
||
|
//
|
||
|
// Advance the ASCII wheel
|
||
|
//
|
||
|
|
||
|
iWheelPosition++;
|
||
|
|
||
|
if( iWheelPosition >= NUMBER_OF_ASCII_WHEEL_SYMBOLS )
|
||
|
{
|
||
|
iWheelPosition = 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We are done copying the disk so force it to read 100% and get rid of
|
||
|
// the ascii wheel symbol.
|
||
|
//
|
||
|
ConsolePrint( L" 100%% %s. \n", StrComplete );
|
||
|
|
||
|
//
|
||
|
// Free allocated resources
|
||
|
//
|
||
|
CleanUp( &hFloppyDrive, &hFloppyImage );
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: PrintErrorMessage
|
||
|
//
|
||
|
// Purpose: To get the last system error, look up what it is and print it out
|
||
|
// to the user.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
PrintErrorMessage( VOID )
|
||
|
{
|
||
|
|
||
|
LPVOID lpMsgBuf = NULL;
|
||
|
|
||
|
if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL,
|
||
|
GetLastError(),
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(LPWSTR) &lpMsgBuf,
|
||
|
0,
|
||
|
NULL )) {
|
||
|
// Great. Not enough memory to format an error message.
|
||
|
ConsolePrint( L"\nNot enough memory to format error message.\n" );
|
||
|
if( lpMsgBuf )
|
||
|
LocalFree( lpMsgBuf );
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
ConsolePrint( L"\n%s\n", (LPCWSTR)lpMsgBuf );
|
||
|
|
||
|
LocalFree( lpMsgBuf );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: PrintErrorWrongDriveType
|
||
|
//
|
||
|
// Purpose: To translate a drive type error code into a message and print it
|
||
|
//
|
||
|
// Arguments: UINT iDriveType - drive type error code to look-up
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
PrintErrorWrongDriveType( UINT iDriveType )
|
||
|
{
|
||
|
|
||
|
if( iDriveType == DRIVE_NO_ROOT_DIR )
|
||
|
{
|
||
|
WCHAR *StrNoRootDir = MyLoadString( IDS_NO_ROOT_DIR );
|
||
|
|
||
|
ConsolePrint( L"\n%s\n", StrNoRootDir );
|
||
|
|
||
|
free( StrNoRootDir );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WCHAR *StrDriveNotFloppy = MyLoadString( IDS_DRIVE_NOT_FL0PPY );
|
||
|
|
||
|
ConsolePrint( L"\n%s\n", StrDriveNotFloppy );
|
||
|
|
||
|
free( StrDriveNotFloppy );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsDriveLargeEnough
|
||
|
//
|
||
|
// Purpose: To determine if the floppy drive supports 1.44 MB or larger disks
|
||
|
//
|
||
|
// Arguments: char* DrivePath - drive path of the floppy to write to, it is of
|
||
|
// the form \\.\x where x is the drive letter
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if the drive supports 1.44 MB or greater, FALSE if not
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
IsDriveLargeEnough( WCHAR *DrivePath )
|
||
|
{
|
||
|
|
||
|
UINT i;
|
||
|
HANDLE hFloppyDrive;
|
||
|
DISK_GEOMETRY SupportedGeometry[20];
|
||
|
DWORD SupportedGeometryCount;
|
||
|
DWORD ReturnedByteCount;
|
||
|
|
||
|
hFloppyDrive = CreateFile( DrivePath,
|
||
|
0,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_ALWAYS,
|
||
|
0,
|
||
|
NULL );
|
||
|
|
||
|
if( hFloppyDrive == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
|
||
|
PrintErrorMessage();
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
if( DeviceIoControl( hFloppyDrive,
|
||
|
IOCTL_DISK_GET_MEDIA_TYPES,
|
||
|
NULL,
|
||
|
0,
|
||
|
SupportedGeometry,
|
||
|
sizeof( SupportedGeometry ),
|
||
|
&ReturnedByteCount,
|
||
|
NULL ) )
|
||
|
{
|
||
|
|
||
|
SupportedGeometryCount = ( ReturnedByteCount / sizeof( DISK_GEOMETRY ) );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SupportedGeometryCount = 0;
|
||
|
}
|
||
|
|
||
|
CloseHandle( hFloppyDrive );
|
||
|
|
||
|
for( i = 0; i < SupportedGeometryCount; i++ )
|
||
|
{
|
||
|
|
||
|
if( SupportedGeometry[i].MediaType == F3_1Pt44_512 )
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// This drive supports 3.5, 1.44MB, 512 bytes/sector.
|
||
|
//
|
||
|
return( TRUE );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return( FALSE );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DoImageFilesExist
|
||
|
//
|
||
|
// Purpose: Determines if all the image files are in the current directory or
|
||
|
// not. If an image file is missing, an error message is printed
|
||
|
// to the user.
|
||
|
//
|
||
|
// Note: it detemines if a file exists by seeing if it can open it
|
||
|
// for reading.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: INT -- non-zero on success, all images files exist in current dir
|
||
|
// zero on failure, 1 or more image files do not exist
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
INT
|
||
|
DoImageFilesExist( VOID )
|
||
|
{
|
||
|
|
||
|
BOOL bAllFilesExist = TRUE;
|
||
|
|
||
|
if( ! DoesFileExist( NT_IMAGE_1_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_1_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
if( ! DoesFileExist( NT_IMAGE_2_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_2_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
if( ! DoesFileExist( NT_IMAGE_3_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_3_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
if( ! DoesFileExist( NT_IMAGE_4_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_4_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
if( ! DoesFileExist( NT_IMAGE_5_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_5_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
if( ! DoesFileExist( NT_IMAGE_6_NAME ) )
|
||
|
{
|
||
|
print( StrCanNotFindFile, NT_IMAGE_6_NAME );
|
||
|
bAllFilesExist = FALSE;
|
||
|
}
|
||
|
|
||
|
if( bAllFilesExist )
|
||
|
{
|
||
|
return( 1 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CleanUp
|
||
|
//
|
||
|
// Purpose: Closes open handles. This function should be called just before
|
||
|
// exiting the program.
|
||
|
//
|
||
|
// Arguments: HANDLE *hFloppyDrive - the floppy disk handle to be closed
|
||
|
// HANDLE *hFloppyImage - the floppy image file handle to be closed
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
CleanUp( HANDLE *hFloppyDrive, HANDLE *hFloppyImage )
|
||
|
{
|
||
|
|
||
|
if( *hFloppyDrive )
|
||
|
{
|
||
|
CloseHandle( *hFloppyDrive );
|
||
|
*hFloppyDrive = NULL;
|
||
|
}
|
||
|
|
||
|
if( *hFloppyImage )
|
||
|
{
|
||
|
CloseHandle( *hFloppyImage );
|
||
|
*hFloppyImage = NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: FreeStrings
|
||
|
//
|
||
|
// Purpose: Deallocate the memory for all the strings.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
FreeStrings( VOID )
|
||
|
{
|
||
|
|
||
|
free( StrNtVersionName );
|
||
|
free( StrDiskLabel1 );
|
||
|
free( StrDiskLabel2 );
|
||
|
free( StrDiskLabel3 );
|
||
|
free( StrDiskLabel4 );
|
||
|
free( StrDiskLabel5 );
|
||
|
free( StrDiskLabel6 );
|
||
|
|
||
|
free( StrStars );
|
||
|
free( StrExplanationLine1 );
|
||
|
free( StrExplanationLine2 );
|
||
|
free( StrExplanationLine3 );
|
||
|
free( StrExplanationLine4 );
|
||
|
free( StrInsertFirstDiskLine1 );
|
||
|
free( StrInsertFirstDiskLine2 );
|
||
|
free( StrInsertAnotherDiskLine1 );
|
||
|
free( StrInsertAnotherDiskLine2 );
|
||
|
free( StrPressAnyKeyWhenReady );
|
||
|
free( StrCompletedSuccessfully );
|
||
|
free( StrComplete );
|
||
|
|
||
|
free( StrCanNotFindFile );
|
||
|
|
||
|
free( StrOutOfMemory );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: LoadStrings
|
||
|
//
|
||
|
// Purpose: Load the string constants from the string table.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
LoadStrings( VOID )
|
||
|
{
|
||
|
|
||
|
INT Length;
|
||
|
|
||
|
//
|
||
|
// Loading the Out of Memory string is a little tricky because of the
|
||
|
// error that can occur while loading it.
|
||
|
//
|
||
|
// For the other strings, just call the MyLoadString function to do
|
||
|
// the work
|
||
|
//
|
||
|
StrOutOfMemory = (WCHAR *) malloc( MAKEBOOT_MAX_STRING_LEN * sizeof(WCHAR) + 1 );
|
||
|
|
||
|
if( StrOutOfMemory == NULL )
|
||
|
{
|
||
|
//
|
||
|
// Can't localize this string
|
||
|
//
|
||
|
ConsolePrint( L"\nOut of memory. Please free more memory and run this program again.\n" );
|
||
|
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
Length = LoadString( NULL,
|
||
|
IDS_OUT_OF_MEMORY,
|
||
|
StrOutOfMemory,
|
||
|
MAKEBOOT_MAX_STRING_LEN );
|
||
|
|
||
|
if( ! Length )
|
||
|
{
|
||
|
//
|
||
|
// Can't localize this string
|
||
|
//
|
||
|
ConsolePrint( L"Unable to load resources.\n" );
|
||
|
|
||
|
exit( 1 ) ;
|
||
|
}
|
||
|
|
||
|
StrStars = MyLoadString( IDS_STARS );
|
||
|
StrExplanationLine1 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_1 );
|
||
|
StrExplanationLine2 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_2 );
|
||
|
StrExplanationLine3 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_3 );
|
||
|
StrExplanationLine4 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_4 );
|
||
|
|
||
|
StrInsertFirstDiskLine1 = MyLoadString( IDS_INSERT_FIRST_DISK_LINE_1 );
|
||
|
StrInsertFirstDiskLine2 = MyLoadString( IDS_INSERT_FIRST_DISK_LINE_2 );
|
||
|
|
||
|
StrInsertAnotherDiskLine1 = MyLoadString( IDS_INSERT_ANOTHER_DISK_LINE_1 );
|
||
|
StrInsertAnotherDiskLine2 = MyLoadString( IDS_INSERT_ANOTHER_DISK_LINE_2 );
|
||
|
|
||
|
StrPressAnyKeyWhenReady = MyLoadString( IDS_PRESS_ANY_KEY_WHEN_READY );
|
||
|
|
||
|
StrCompletedSuccessfully = MyLoadString( IDS_COMPLETED_SUCCESSFULLY );
|
||
|
StrComplete = MyLoadString( IDS_COMPLETE );
|
||
|
|
||
|
StrCanNotFindFile = MyLoadString( IDS_CANNOT_FIND_FILE );
|
||
|
|
||
|
StrNtVersionName = MyLoadString( IDS_NT_VERSION_NAME_DEFAULT );
|
||
|
StrDiskLabel1 = MyLoadString( IDS_DISK_LABEL_1_DEFAULT );
|
||
|
StrDiskLabel2 = MyLoadString( IDS_DISK_LABEL_2_DEFAULT );
|
||
|
StrDiskLabel3 = MyLoadString( IDS_DISK_LABEL_3_DEFAULT );
|
||
|
StrDiskLabel4 = MyLoadString( IDS_DISK_LABEL_4_DEFAULT );
|
||
|
StrDiskLabel5 = MyLoadString( IDS_DISK_LABEL_5_DEFAULT );
|
||
|
StrDiskLabel6 = MyLoadString( IDS_DISK_LABEL_6_DEFAULT );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DoesUserWantToTryCopyAgain
|
||
|
//
|
||
|
// Purpose: Ask the user if they want to retry to copy the image to floppy.
|
||
|
// Get the user input and return whether to copy again or not.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if user wants to attempt to copy again
|
||
|
// - FALSE if user does not want to attempt to copy again
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
DoesUserWantToTryCopyAgain( VOID )
|
||
|
{
|
||
|
|
||
|
INT ch;
|
||
|
|
||
|
WCHAR *StrAttemptToCreateFloppyAgain = MyLoadString( IDS_ATTEMPT_TO_CREATE_FLOPPY_AGAIN );
|
||
|
WCHAR *StrPressEnterOrEsc = MyLoadString( IDS_PRESS_ENTER_OR_ESC );
|
||
|
|
||
|
//
|
||
|
// Clear the input stream by eating all the chars until there are none
|
||
|
// left. Print the message and then wait for a key press.
|
||
|
//
|
||
|
while( _kbhit() )
|
||
|
{
|
||
|
_getch();
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
ConsolePrint( L"%s\n", StrAttemptToCreateFloppyAgain );
|
||
|
ConsolePrint( L"%s\n", StrPressEnterOrEsc );
|
||
|
|
||
|
ch = _getch();
|
||
|
|
||
|
} while( ch != ENTER_KEY && ch != ESC_KEY );
|
||
|
|
||
|
if( ch == ENTER_KEY )
|
||
|
{
|
||
|
return( TRUE );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
free( StrAttemptToCreateFloppyAgain );
|
||
|
free( StrPressEnterOrEsc );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: PressAnyKeyToContinue
|
||
|
//
|
||
|
// Purpose: Print the "Press any key when ready" message and wait until the
|
||
|
// user presses a key.
|
||
|
//
|
||
|
// Arguments: VOID
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
PressAnyKeyToContinue( VOID )
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Clear the input stream by eating all the chars until there are none
|
||
|
// left. Print the message and then wait for a key press.
|
||
|
//
|
||
|
while( _kbhit() )
|
||
|
{
|
||
|
_getch();
|
||
|
}
|
||
|
|
||
|
print( StrPressAnyKeyWhenReady );
|
||
|
|
||
|
//
|
||
|
// Spin until the keyboard is pressed
|
||
|
//
|
||
|
while( ! _kbhit() )
|
||
|
{
|
||
|
;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MyLoadString
|
||
|
//
|
||
|
// Purpose: Loads a string resource given it's IDS_* and returns
|
||
|
// a malloc'ed buffer with its contents.
|
||
|
//
|
||
|
// The malloc()'ed buffer must be freed with free()
|
||
|
//
|
||
|
// This function will either return the string or exit. It will
|
||
|
// never return NULL or a bad pointer.
|
||
|
//
|
||
|
// Arguments: UINT StringId - the string ID to load
|
||
|
//
|
||
|
// Returns:
|
||
|
// Pointer to buffer. An empty string is returned if the StringId
|
||
|
// does not exist. Null is returned if out of memory.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
LPWSTR
|
||
|
MyLoadString( UINT StringId )
|
||
|
{
|
||
|
|
||
|
WCHAR Buffer[ MAKEBOOT_MAX_STRING_LEN ];
|
||
|
WCHAR *String = NULL;
|
||
|
UINT Length;
|
||
|
|
||
|
Length = LoadString( NULL,
|
||
|
StringId,
|
||
|
Buffer,
|
||
|
MAKEBOOT_MAX_STRING_LEN );
|
||
|
|
||
|
if( Length )
|
||
|
{
|
||
|
|
||
|
String = (WCHAR *) malloc( Length * sizeof(WCHAR) + 1 );
|
||
|
|
||
|
if( String == NULL )
|
||
|
{
|
||
|
|
||
|
ConsolePrint( L"%s\n", StrOutOfMemory );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
wcscpy( String, Buffer );
|
||
|
String[Length] = L'\0';
|
||
|
|
||
|
return( String );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Can't load the string so exit
|
||
|
// NOTE: this string will not be localized
|
||
|
//
|
||
|
ConsolePrint( L"Unable to load resources.\n" );
|
||
|
|
||
|
exit( 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: print
|
||
|
//
|
||
|
// Purpose: To print out strings to the user. Useful when there is
|
||
|
// embedded formatting characters in a string that was loaded from
|
||
|
// a string table.
|
||
|
//
|
||
|
// Arguments: szFirstString - the string that contains the embedded formatting
|
||
|
// characters (such as %s, %c, etc.)
|
||
|
// ... - variable number of arguments that correspond to each
|
||
|
// formatting character
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
print( WCHAR *szFirstString, ... )
|
||
|
{
|
||
|
|
||
|
WCHAR OutputBuffer[MAKEBOOT_MAX_STRING_LEN];
|
||
|
va_list arglist;
|
||
|
|
||
|
va_start( arglist, szFirstString );
|
||
|
|
||
|
wvsprintf( OutputBuffer, szFirstString, arglist );
|
||
|
|
||
|
ConsolePrint( L"%s\n", OutputBuffer );
|
||
|
|
||
|
va_end( arglist );
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DoesFileExist
|
||
|
//
|
||
|
// Purpose: To determine whether a file exists or not
|
||
|
//
|
||
|
// Arguments: LPWSTR lpFileName - filename to see if it exists or not
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if the file exists
|
||
|
// - FALSE if the file does not exist
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
DoesFileExist( LPWSTR lpFileName )
|
||
|
{
|
||
|
DWORD dwAttribs = GetFileAttributes( lpFileName );
|
||
|
|
||
|
if( dwAttribs == (DWORD) -1 )
|
||
|
{
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
if( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
|
||
|
{
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsDBCSConsole
|
||
|
//
|
||
|
// Purpose: To determine whether a DBC console or not
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: BOOL - TRUE if FE console codepage
|
||
|
// - FALSE if not FE console codepage
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
IsDBCSCodePage(UINT CodePage)
|
||
|
{
|
||
|
switch(CodePage) {
|
||
|
case 932:
|
||
|
case 936:
|
||
|
case 949:
|
||
|
case 950:
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SetFarEastThread
|
||
|
//
|
||
|
// Purpose: FarEast version wants to display bi-lingual string according console OCP
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: None
|
||
|
//----------------------------------------------------------------------------
|
||
|
void SetFarEastThread()
|
||
|
{
|
||
|
LANGID LangId = 0;
|
||
|
|
||
|
switch(GetConsoleOutputCP()) {
|
||
|
case 932:
|
||
|
LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT );
|
||
|
break;
|
||
|
case 949:
|
||
|
LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN );
|
||
|
break;
|
||
|
case 936:
|
||
|
LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );
|
||
|
break;
|
||
|
case 950:
|
||
|
LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL );
|
||
|
break;
|
||
|
default:
|
||
|
{
|
||
|
LANGID TmpLangId = PRIMARYLANGID(LANGIDFROMLCID( GetUserDefaultLCID() ));
|
||
|
|
||
|
if (TmpLangId == LANG_JAPANESE ||
|
||
|
TmpLangId == LANG_KOREAN ||
|
||
|
TmpLangId == LANG_CHINESE ) {
|
||
|
LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (LangId) {
|
||
|
SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConsolePrint
|
||
|
//
|
||
|
// Purpose: There is a bug in CRT library that unicode FE characters can't
|
||
|
// convert correctly, so we output characters directly.
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: None
|
||
|
//----------------------------------------------------------------------------
|
||
|
void ConsolePrint( WCHAR *szFirstString, ... )
|
||
|
{
|
||
|
HANDLE StdOut;
|
||
|
DWORD WrittenCount;
|
||
|
WCHAR OutputBuffer[MAKEBOOT_MAX_STRING_LEN];
|
||
|
va_list arglist;
|
||
|
|
||
|
if((StdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
va_start( arglist, szFirstString );
|
||
|
|
||
|
wvsprintf( OutputBuffer, szFirstString, arglist );
|
||
|
|
||
|
WriteConsoleW(
|
||
|
StdOut,
|
||
|
OutputBuffer,
|
||
|
lstrlenW(OutputBuffer),
|
||
|
&WrittenCount,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
va_end( arglist );
|
||
|
}
|