200 lines
5.6 KiB
C
200 lines
5.6 KiB
C
#include <windows.h>
|
|
#include <winioctl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
typedef struct _BOOT_SECTOR_ZERO {
|
|
UCHAR IntelNearJumpCommand[1];
|
|
UCHAR BootStrapJumpOffset[2];
|
|
UCHAR OemData[8];
|
|
UCHAR BytesPerSector[2];
|
|
UCHAR SectorsPerCluster[1];
|
|
UCHAR ReservedSectors[2];
|
|
UCHAR Fats[1];
|
|
UCHAR RootEntries[2];
|
|
UCHAR Sectors[2];
|
|
UCHAR Media[1];
|
|
UCHAR SectorsPerFat[2];
|
|
UCHAR SectorsPerTrack[2];
|
|
UCHAR Heads[2];
|
|
UCHAR HiddenSectors[4];
|
|
UCHAR LargeSectors[4];
|
|
UCHAR PhysicalDrive[1];
|
|
UCHAR CurrentHead[1];
|
|
UCHAR Signature[1];
|
|
UCHAR SerialNumber[4];
|
|
UCHAR Label[11];
|
|
UCHAR SystemIdText[8];
|
|
} *PBOOT_SECTOR;
|
|
|
|
int
|
|
_cdecl
|
|
main(
|
|
int argc,
|
|
char** argv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements a DMF format. It lays down the BPB and everything.
|
|
|
|
Arguments:
|
|
|
|
argc - Supplies the number of command line arguments.
|
|
|
|
argv - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
0 - Success.
|
|
|
|
1 - Failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
#define FORMAT_PARAMETERS_SIZE (sizeof(FORMAT_EX_PARAMETERS) + 20*sizeof(USHORT))
|
|
|
|
CHAR drive[20];
|
|
HANDLE handle;
|
|
CHAR formatParametersBuffer[FORMAT_PARAMETERS_SIZE];
|
|
PFORMAT_EX_PARAMETERS formatParameters;
|
|
ULONG i, next;
|
|
BOOL b;
|
|
PUCHAR trackBuffer;
|
|
ULONG trackSize;
|
|
PBOOT_SECTOR bootSector;
|
|
DWORD bytesWritten;
|
|
USHORT swapBuffer[3];
|
|
|
|
// First make sure that we have at least one parameter.
|
|
|
|
if (argc < 2) {
|
|
printf("usage: %s drive:\n", argv[0]);
|
|
return(1);
|
|
}
|
|
|
|
|
|
// Open the drive for exclusive access.
|
|
|
|
sprintf(drive, "\\\\.\\%s", argv[1]);
|
|
handle = CreateFile(drive, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|
OPEN_EXISTING, 0, NULL);
|
|
if (handle == INVALID_HANDLE_VALUE) {
|
|
printf("can't open drive %s, error = %d\n", argv[1], GetLastError());
|
|
return(1);
|
|
}
|
|
|
|
|
|
// Prepare the format parameters.
|
|
|
|
formatParameters = (PFORMAT_EX_PARAMETERS) formatParametersBuffer;
|
|
formatParameters->MediaType = F3_1Pt44_512;
|
|
formatParameters->FormatGapLength = 8;
|
|
formatParameters->SectorsPerTrack = 21;
|
|
|
|
next = 0;
|
|
for (i = 0; i < formatParameters->SectorsPerTrack; i += 2) {
|
|
formatParameters->SectorNumber[i] = (USHORT) (i/2 + 1);
|
|
next++;
|
|
}
|
|
|
|
for (i = 1; i < formatParameters->SectorsPerTrack; i += 2) {
|
|
formatParameters->SectorNumber[i] = (USHORT) (i/2 + next + 1);
|
|
}
|
|
|
|
// Start off by putting the boot sector as the last sector of
|
|
// the first track.
|
|
|
|
MoveMemory(&formatParameters->SectorNumber[0],
|
|
&formatParameters->SectorNumber[1],
|
|
20*sizeof(USHORT));
|
|
formatParameters->SectorNumber[20] = 1;
|
|
|
|
|
|
// Format each track on the floppy.
|
|
|
|
for (i = 0; i < 80; i++) {
|
|
|
|
formatParameters->StartCylinderNumber =
|
|
formatParameters->EndCylinderNumber = i;
|
|
formatParameters->StartHeadNumber = 0;
|
|
formatParameters->EndHeadNumber = 1;
|
|
|
|
printf("Formatting track %d\r", i);
|
|
|
|
b = DeviceIoControl(handle, IOCTL_DISK_FORMAT_TRACKS_EX,
|
|
formatParameters, FORMAT_PARAMETERS_SIZE,
|
|
NULL, 0, &bytesWritten, NULL);
|
|
|
|
if (!b) {
|
|
printf("Could not format track %d, error = %d\n", i, GetLastError());
|
|
return(1);
|
|
}
|
|
|
|
|
|
// Skew the next cylinder by 3 sectors from this one.
|
|
|
|
MoveMemory(swapBuffer,
|
|
&formatParameters->SectorNumber[18],
|
|
3*sizeof(USHORT));
|
|
MoveMemory(&formatParameters->SectorNumber[3],
|
|
&formatParameters->SectorNumber[0],
|
|
18*sizeof(USHORT));
|
|
MoveMemory(&formatParameters->SectorNumber[0],
|
|
swapBuffer,
|
|
3*sizeof(USHORT));
|
|
|
|
}
|
|
|
|
|
|
// Write out the boot sector, the FAT, and the root directory.
|
|
|
|
trackSize = formatParameters->SectorsPerTrack*512;
|
|
trackBuffer = LocalAlloc(LMEM_FIXED, trackSize + 0x1FF);
|
|
trackBuffer = (PUCHAR) (((ULONG) (trackBuffer + 0x1FF))&(~0x1FF));
|
|
ZeroMemory(trackBuffer, trackSize);
|
|
bootSector = (PBOOT_SECTOR) trackBuffer;
|
|
|
|
bootSector->IntelNearJumpCommand[0] = 0xeb;
|
|
bootSector->BootStrapJumpOffset[0] = 0x3e;
|
|
bootSector->BootStrapJumpOffset[1] = 0x90;
|
|
CopyMemory(bootSector->OemData, "NSDMF3.2", 8);
|
|
bootSector->BytesPerSector[1] = 2;
|
|
bootSector->SectorsPerCluster[0] = 4;
|
|
bootSector->ReservedSectors[0] = 1;
|
|
bootSector->Fats[0] = 2;
|
|
bootSector->RootEntries[0] = 0x10;
|
|
bootSector->Sectors[0] = 0x20;
|
|
bootSector->Sectors[1] = 0xd;
|
|
bootSector->Media[0] = 0xf0;
|
|
bootSector->SectorsPerFat[0] = 3;
|
|
bootSector->SectorsPerTrack[0] = 0x15;
|
|
bootSector->Heads[0] = 2;
|
|
bootSector->Signature[0] = 0x29;
|
|
CopyMemory(bootSector->Label, "NO NAME ", 11);
|
|
CopyMemory(bootSector->SystemIdText, "FAT12 ", 8);
|
|
|
|
trackBuffer[0x1fe] = 0x55;
|
|
trackBuffer[0x1ff] = 0xAA;
|
|
trackBuffer[0x200] = 0xF0;
|
|
trackBuffer[0x201] = 0xFF;
|
|
trackBuffer[0x202] = 0xFF;
|
|
trackBuffer[0x800] = 0xF0;
|
|
trackBuffer[0x801] = 0xFF;
|
|
trackBuffer[0x802] = 0xFF;
|
|
|
|
b = WriteFile(handle, trackBuffer, trackSize, &bytesWritten, NULL);
|
|
if (!b || trackSize != bytesWritten) {
|
|
printf("Track 0 write failed with %d\n", GetLastError());
|
|
return(1);
|
|
}
|
|
|
|
CloseHandle(handle);
|
|
|
|
return(0);
|
|
}
|