/*++ Module Name: mfmt.c Abstract: This program is designed to show how to access a physical floppy disk using the Win32 API set. This program has two major functions. - It can be used to display the geometry of a disk mfmt -g a: - It can be used to produce a disk image, or to write a disk image to a floppy. mfmt -c a: bootdisk - produce a disk image of a: mfmt -c bootdisk a: - make a: identical to bootdisk image This program is very very simple. Minimal error checking is done. It is meant to provide an example of how to: - Open a physical disk - Read a disk's geometry - Perform a low level format operation - read and write physical sectors Author: Some Guy in the NT group (sgitng) 05-Oct-1992 Revision History: --*/ #include #include #include #include #include #include DISK_GEOMETRY SupportedGeometry[20]; DWORD SupportedGeometryCount; BOOL GetDiskGeometry( HANDLE hDisk, PDISK_GEOMETRY lpGeometry ) { DWORD ReturnedByteCount; return DeviceIoControl( hDisk, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, lpGeometry, sizeof(*lpGeometry), &ReturnedByteCount, NULL ); } DWORD GetSupportedGeometrys( HANDLE hDisk ) { DWORD ReturnedByteCount; BOOL b; DWORD NumberSupported; b = DeviceIoControl( hDisk, IOCTL_DISK_GET_MEDIA_TYPES, NULL, 0, SupportedGeometry, sizeof(SupportedGeometry), &ReturnedByteCount, NULL ); if ( b ) { NumberSupported = ReturnedByteCount / sizeof(DISK_GEOMETRY); } else { NumberSupported = 0; } SupportedGeometryCount = NumberSupported; return NumberSupported; } VOID PrintGeometry( LPSTR lpDriveName, PDISK_GEOMETRY lpGeometry ) { LPSTR MediaType; if (lpDriveName) { printf("Geometry for Drive %s\n",lpDriveName); } switch ( lpGeometry->MediaType ) { case F5_1Pt2_512: MediaType = "5.25, 1.2MB, 512 bytes/sector";break; case F3_1Pt44_512: MediaType = "3.5, 1.44MB, 512 bytes/sector";break; case F3_2Pt88_512: MediaType = "3.5, 2.88MB, 512 bytes/sector";break; case F3_20Pt8_512: MediaType = "3.5, 20.8MB, 512 bytes/sector";break; case F3_720_512: MediaType = "3.5, 720KB, 512 bytes/sector";break; case F5_360_512: MediaType = "5.25, 360KB, 512 bytes/sector";break; case F5_320_512: MediaType = "5.25, 320KB, 512 bytes/sector";break; case F5_320_1024: MediaType = "5.25, 320KB, 1024 bytes/sector";break; case F5_180_512: MediaType = "5.25, 180KB, 512 bytes/sector";break; case F5_160_512: MediaType = "5.25, 160KB, 512 bytes/sector";break; case RemovableMedia: MediaType = "Removable media other than floppy";break; case FixedMedia: MediaType = "Fixed hard disk media";break; default: MediaType = "Unknown";break; } printf(" Media Type %s\n",MediaType); printf(" Cylinders %d Tracks/Cylinder %d Sectors/Track %d\n", lpGeometry->Cylinders.LowPart, lpGeometry->TracksPerCylinder, lpGeometry->SectorsPerTrack ); } BOOL LowLevelFormat( HANDLE hDisk, PDISK_GEOMETRY lpGeometry ) { FORMAT_PARAMETERS FormatParameters; PBAD_TRACK_NUMBER lpBadTrack; UINT i; BOOL b; DWORD ReturnedByteCount; FormatParameters.MediaType = lpGeometry->MediaType; FormatParameters.StartHeadNumber = 0; FormatParameters.EndHeadNumber = lpGeometry->TracksPerCylinder - 1; lpBadTrack = (PBAD_TRACK_NUMBER) LocalAlloc(LMEM_ZEROINIT,lpGeometry->TracksPerCylinder*sizeof(*lpBadTrack)); for (i = 0; i < lpGeometry->Cylinders.LowPart; i++) { FormatParameters.StartCylinderNumber = i; FormatParameters.EndCylinderNumber = i; b = DeviceIoControl( hDisk, IOCTL_DISK_FORMAT_TRACKS, &FormatParameters, sizeof(FormatParameters), lpBadTrack, lpGeometry->TracksPerCylinder*sizeof(*lpBadTrack), &ReturnedByteCount, NULL ); if (!b ) { LocalFree(lpBadTrack); return b; } } LocalFree(lpBadTrack); return TRUE; } BOOL LockVolume( HANDLE hDisk ) { DWORD ReturnedByteCount; return DeviceIoControl( hDisk, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &ReturnedByteCount, NULL ); } BOOL UnlockVolume( HANDLE hDisk ) { DWORD ReturnedByteCount; return DeviceIoControl( hDisk, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &ReturnedByteCount, NULL ); } BOOL DismountVolume( HANDLE hDisk ) { DWORD ReturnedByteCount; return DeviceIoControl( hDisk, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &ReturnedByteCount, NULL ); } DWORD _cdecl main( int argc, char *argv[], char *envp[] ) { char Drive[MAX_PATH]; HANDLE hDrive, hDiskImage; DISK_GEOMETRY Geometry; UINT i; char c, *p; LPSTR DriveName; BOOL fUsage = TRUE; BOOL fShowGeometry = FALSE; BOOL fDiskImage = FALSE; BOOL SourceIsDrive; LPSTR Source, Destination, DiskImage; if ( argc > 1 ) { fUsage = FALSE; while (--argc) { p = *++argv; if (*p == '/' || *p == '-') { while (c = *++p) switch (toupper( c )) { case '?': fUsage = TRUE; break; case 'C': fDiskImage = TRUE; argc--, argv++; Source = *argv; argc--, argv++; Destination = *argv; break; case 'G': fShowGeometry = TRUE; argc--, argv++; DriveName = *argv; break; default: printf("MFMT: Invalid switch - /%c\n", c ); fUsage = TRUE; break; } } } } if ( fUsage ) { printf("usage: MFMT switches \n" ); printf(" [-?] display this message\n" ); printf(" [-g drive] shows disk geometry\n" ); printf(" [-c source destination] produce diskimage\n" ); ExitProcess(1); } if ( fShowGeometry ) { sprintf(Drive,"\\\\.\\%s",DriveName); hDrive = CreateFile( Drive, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if ( hDrive == INVALID_HANDLE_VALUE ) { printf("MFMT: Open %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } LockVolume(hDrive); if ( !GetDiskGeometry(hDrive,&Geometry) ) { printf("MFMT: GetDiskGeometry %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } PrintGeometry(DriveName,&Geometry); if ( !GetSupportedGeometrys(hDrive) ) { printf("MFMT: GetSupportedGeometrys %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } printf("\nDrive %s supports the following disk geometries\n",DriveName); for(i=0;i= FileSize ) { IoBuffer = VirtualAlloc(NULL,GeometrySize,MEM_COMMIT,PAGE_READWRITE); if ( !IoBuffer ) { printf("MFMT: Buffer Allocation Failed\n"); ExitProcess(1); } // // Format the floppy // LowLevelFormat(hDrive,&SupportedGeometry[i]); b = ReadFile(hDiskImage,IoBuffer, GeometrySize, &BytesRead, NULL); if (b && BytesRead){ b = WriteFile(hDrive,IoBuffer, BytesRead, &BytesWritten, NULL); if ( !b || ( BytesRead != BytesWritten ) ) { printf("MFMT: Fatal Write Error %d\n",GetLastError()); ExitProcess(1); } } else { printf("MFMT: Fatal Read Error %d\n",GetLastError()); ExitProcess(1); } b = TRUE; break; } } if ( !b ) { printf("MFMT: FileSize %d is not supported on drive %s\n",FileSize,DriveName); ExitProcess(1); } } } // // Dismounting forces the filesystem to re-evaluate the media id // and geometry. This is the same as popping the floppy in and out // of the disk drive // DismountVolume(hDrive); UnlockVolume(hDrive); ExitProcess(0); } }