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.
 
 
 
 
 
 

583 lines
15 KiB

/****************************************************************************\
*
*
* Module: dskimage.c
*
* Description: This is the main module of the dskimage utility.
*
* Arguments: dskimage <source> <destination> [/F | /f]
*
* where <source> is the source of the diskette
* image
* <destination> is the destination of the diskette
* image
* /F or /f indicates that the floppy should
* be formatted
*
* The source or destination must be a valid floppy drive
* name.
*
* Comments: This utility was not ported from the OS/2 version.
* It was developed separately. This file is written
* for Win32, with no references to physical disk access
* required in NT. See ntphys.c for direct floppy
* access.
*
* Author: Kenneth S. Gregg (kengr)
*
* Copyright (c) 1991 Microsoft Corporation
*
* History: 10/20/91 - original version (kengr)
* 05/31/92 - fix bug #10607 - access violation due
* to incorrect argc checking in main.
*
*
\****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include "physdisk.h" /* functions for floppy access */
#include "bootsect.h" /* boot sector layout */
#define BUFFER_SIZE ((DWORD)(64*1024)) /* internal data buffer size */
#define FLOP_360K (360*1024) /* size of 360K floppies */
#define FLOP_720K (720*1024) /* size of 720K floppies */
#define ERROR_RET (-1) /* returned from main on error */
PUCHAR uchBuffer;
/****************************************************************************\
*
*
* Function: CleanUp
*
* Description: This internal function provides cleanup services common
* to both MakeFile and MakeFloppy. The file name is passed
* in for error reporting only.
*
* Arguments: Name of image file to be closed.
* Stream pointer of image file to be closed.
* Handle of data buffer to be released.
*
* Returns: Boolean, TRUE if all operations succeeded.
*
* Comments:
*
*
\****************************************************************************/
static BOOL CleanUp(
LPSTR lpFileName, /* File name to be closed */
FILE *fp) /* stream of file to be closed */
{
BOOL bResult = TRUE; /* assume success until fail */
/* Close the image file we opened. */
if (fclose(fp) != 0) {
printf("Unable to close %s\n", lpFileName);
bResult = FALSE;
}
/* Close/release the floppy drive. */
if (CloseFloppy() == FALSE) {
bResult = FALSE;
}
return (bResult);
}
/****************************************************************************\
*
*
* Function: FloppySize
*
* Description: This internal function calculates the number if bytes
* on a floppy, given a pointer to the boot sector. If the
* size cannot be determined, 0 is returned,
*
* Arguments: Pointer to the floppy boot sector.
*
* Returns: Number of bytes on the floppy.
*
* Comments:
*
*
\****************************************************************************/
static DWORD FloppySize(
PBOOTSECTOR pBootSector)
{
DWORD dwSectorSize = 0;
DWORD dwSectorCount = 0;
DWORD dwByteCount = 0;
dwSectorSize = pBootSector->bsBPB.bpbBytesPerSector;
dwSectorCount = pBootSector->bsBPB.bpbSectors;
dwByteCount = dwSectorSize * dwSectorCount;
return (dwByteCount);
}
/****************************************************************************\
*
*
* Function: MakeFile
*
* Description: This internal function performs the "copy from floppy
* to file" operation.
*
* Arguments: Name of floppy drive to be read.
* Name of the image file to be created.
*
* Returns: Boolean, TRUE if all operations succeeded.
*
* Comments:
*
*
\****************************************************************************/
static BOOL MakeFile(
char chFloppyName,
LPSTR lpFileName)
{
LPSTR lpMem;
DWORD dwByteCount;
DWORD dwIterations;
DWORD dwRemainder;
DWORD dwOffset;
DWORD dwIndex;
FILE *fp;
size_t stItems;
BOOL bResult;
/* Open the destination file for writing in binary mode. The file will
* be overwitten. If we fail to write anything to the file, we will end
* up with a zero length file.
*/
fp = fopen(lpFileName, "wb");
if (fp == NULL) {
printf("Cannot open %s\n", lpFileName);
return (FALSE);
}
/* Gain access the appropriate floppy drive.
*/
bResult = OpenFloppy(chFloppyName);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
/* Grab the boot sector and figure out how much data needs to be
* transferred.
*/
bResult = ReadFloppy(0, BOOTSECT_SIZE, uchBuffer);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
dwByteCount = FloppySize((PBOOTSECTOR) uchBuffer);
dwIterations = dwByteCount / BUFFER_SIZE;
dwRemainder = dwByteCount % BUFFER_SIZE;
/* Obtain an internal data buffer and lock it down for constant use.
*/
lpMem = VirtualAlloc( NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE );
if (lpMem == NULL) {
printf("Unable to allocate internal buffer.\n");
CleanUp(lpFileName, fp);
return (FALSE);
}
printf("Reading diskette image to file\n");
/* For each iteration, read a block from the floppy, and write it out
* to the disk image file.
*/
for (dwIndex = 0, dwOffset = 0;
dwIndex < dwIterations;
dwIndex++, dwOffset += BUFFER_SIZE) {
printf("%3ld%% complete\r", (100*dwIndex)/dwIterations);
bResult = ReadFloppy(dwOffset, BUFFER_SIZE, lpMem);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
stItems = fwrite(lpMem, BUFFER_SIZE, 1, fp);
if (stItems != 1) {
printf("Unable to write to %s\n", lpFileName);
CleanUp(lpFileName, fp);
return (FALSE);
}
}
/* Read and write the remaining chunk, if any.
*/
if (dwRemainder) {
bResult = ReadFloppy(dwOffset, dwRemainder, lpMem);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
stItems = fwrite(lpMem, dwRemainder, 1, fp);
if (stItems != 1) {
printf("Unable to write to %s\n", lpFileName);
CleanUp(lpFileName, fp);
return (FALSE);
}
}
printf("100%% complete\n");
return (CleanUp(lpFileName, fp));
}
/****************************************************************************\
*
*
* Function: MakeFloppy
*
* Description: This internal function performs the "copy from file
* to floppy" operation.
*
* Arguments: Name of floppy drive to be written.
* Name of the image file to be read.
* Boolean, TRUE if we need to format the floppy.
*
* Returns: Boolean, TRUE if all operations succeeded.
*
* Comments:
*
*
\****************************************************************************/
static BOOL MakeFloppy(
char chFloppyName,
LPSTR lpFileName,
BOOL fFormatFloppy)
{
LPSTR lpMem;
DWORD dwByteCount;
DWORD dwIterations;
DWORD dwRemainder;
DWORD dwOffset;
DWORD dwIndex;
FILE *fp;
size_t stItems;
int iResult;
BOOL bResult;
/* Open the disk image file for reading in binary mode.
*/
fp = fopen(lpFileName, "rb");
if (fp == NULL) {
printf("Cannot open %s\n", lpFileName);
return (FALSE);
}
/* Read the boot sector from the file, and determine how much data
* we are talking about.
*/
stItems = fread(uchBuffer, BOOTSECT_SIZE, 1, fp);
if (stItems != 1) {
printf("Unable to read from %s\n", lpFileName);
return (FALSE);
}
dwByteCount = FloppySize((PBOOTSECTOR) uchBuffer);
dwIterations = dwByteCount / BUFFER_SIZE;
dwRemainder = dwByteCount % BUFFER_SIZE;
/* If we need to format the floppy first, determine if we need to
* format it low-density, to match the disk image file we are
* attempting to copy.
*/
if (fFormatFloppy) {
if ((dwByteCount == FLOP_360K) || (dwByteCount == FLOP_720K)) {
sprintf(uchBuffer, "format %c: /4 /v:nonameLOW < nul\n", chFloppyName);
} else {
sprintf(uchBuffer, "format %c: /v:nonameHIGH < nul\n", chFloppyName);
}
printf("Formatting diskette. Please wait.\n");
system(uchBuffer);
}
/* Now gain access to the floppy drive. Read the boot sector and
* assure that the floppy size matches the number of bytes in the
* disk image file.
*/
bResult = OpenFloppy(chFloppyName);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
bResult = ReadFloppy(0, BOOTSECT_SIZE, uchBuffer);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
if (FloppySize((PBOOTSECTOR) uchBuffer) != dwByteCount) {
printf("Floppy capacity and image file size do not match\n");
CleanUp(lpFileName, fp);
return (FALSE);
}
/* Obtain an internal data buffer and lock it down for constant use.
*/
lpMem = VirtualAlloc( NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE );
if (lpMem == NULL) {
printf("Unable to allocate internal buffer.\n");
CleanUp(lpFileName, fp);
return (FALSE);
}
/* Since we read the boot sector from the file already, reset the
* file pointer to the beginning. (Ok, there's a more efficient
* solution, but who cares...)
*/
iResult = fseek(fp, 0, SEEK_SET);
if (iResult != 0) {
printf("Cannot fseek in %s\n", lpFileName);
CleanUp(lpFileName, fp);
return (FALSE);
}
printf("Reading diskette image to floppy\n");
/* For each iteration, read a block from the file, and write it out
* to the floppy.
*/
for (dwIndex = 0, dwOffset = 0;
dwIndex < dwIterations;
dwIndex++, dwOffset += BUFFER_SIZE) {
printf("%3ld%% complete\r", (100*dwIndex)/dwIterations);
stItems = fread(lpMem, BUFFER_SIZE, 1, fp);
if (stItems != 1) {
printf("Unable to read from %s\n", lpFileName);
CleanUp(lpFileName, fp);
return (FALSE);
}
bResult = WriteFloppy(dwOffset, BUFFER_SIZE, lpMem);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
}
/* Read and write the remaining chunk, if any.
*/
if (dwRemainder) {
stItems = fread(lpMem, dwRemainder, 1, fp);
if (stItems != 1) {
printf("Unable to read from %s\n", lpFileName);
CleanUp(lpFileName, fp);
return (FALSE);
}
bResult = WriteFloppy(dwOffset, dwRemainder, lpMem);
if (bResult == FALSE) {
CleanUp(lpFileName, fp);
return (FALSE);
}
}
printf("100%% complete\n");
return (CleanUp(lpFileName, fp));
}
/****************************************************************************\
*
*
* Function: Usage
*
* Description: This internal function prints syntax information for
* the utility.
*
* Arguments: none
*
* Returns: none
*
* Comments: This function exits the utility.
*
*
\****************************************************************************/
static VOID Usage(VOID)
{
printf("\ndskimage <source> <destination> [/F | /f]\n\n");
printf("where <source> is the source of the diskette image\n");
printf(" <destination> is the destination of the diskette image\n");
printf(" /F or /f indicates that the floppy should be\n");
printf(" formatted.\n\n");
printf("The source or destination must be a valid floppy drive name.\n\n");
}
/****************************************************************************\
*
*
* Function: main
*
* Description: This function reads and interprets the command line
* arguments and then performs the appropriate floppy
* image operation.
*
* Arguments: Command line argument vector
*
* Returns: Non-zero on error.
*
* Comments:
*
*
\****************************************************************************/
int _CRTAPI1 main(
int argc,
char *argv[])
{
CHAR achBuffer[] = "a:\\";
BOOL fFormatFloppy = FALSE;
BOOL fMakeFile = FALSE;
BOOL fMakeFloppy = FALSE;
BOOL fResult = FALSE;
int iResult = 0;
LPSTR lpSource;
LPSTR lpDest;
LPSTR lpOption;
/* Parse the command line arguments.
* There must be 2 or 3 arguments.
*/
uchBuffer = VirtualAlloc( NULL, BOOTSECT_SIZE, MEM_COMMIT, PAGE_READWRITE );
if ((argc < 3) || (argc > 4)) {
Usage();
exit(ERROR_RET);
}
/* Grab the source and destination.
*/
lpSource = argv[1];
lpDest = argv[2];
/* The first two arguments should not be flags.
*/
if ((*lpSource == '/') ||
(*lpSource == '-') ||
(*lpDest == '/') ||
(*lpDest == '-')) {
Usage();
exit(ERROR_RET);
}
/* The third optional argument says whether or not to
* format the floppy first.
*/
if (argc == 4) {
lpOption = argv[3];
fFormatFloppy = ((strcmp(argv[3], "/f") == 0) ||
(strcmp(argv[3], "/F") == 0));
if (!fFormatFloppy) {
Usage();
exit(ERROR_RET);
}
}
/* Determine who is and isn't a floppy.
*/
if ((strlen(lpSource) == 2) && (lpSource[1] == ':')) {
achBuffer[0] = *lpSource;
fMakeFile = (GetDriveType(achBuffer) == DRIVE_REMOVABLE);
}
if ((strlen(lpDest) == 2) && (lpDest[1] == ':')) {
achBuffer[0] = *lpDest;
fMakeFloppy = (GetDriveType(achBuffer) == DRIVE_REMOVABLE);
}
if (fMakeFloppy && fMakeFile) {
printf("Cannot specify two floppy drives.\n");
exit(ERROR_RET);
}
if (!fMakeFloppy && !fMakeFile) {
printf("Need to specify a floppy drive.\n");
exit(ERROR_RET);
}
/* Go do the actual work of imaging.
*/
if (fMakeFloppy) {
fResult = MakeFloppy(*lpDest, lpSource, fFormatFloppy);
} else {
if (fFormatFloppy) {
printf("Format option will be ignored.\n");
}
fResult = MakeFile(*lpSource, lpDest);
}
return ((fResult) ? 0 : ERROR_RET);
}