home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / io / floppy / mfmt.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  17KB  |  554 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*++
  13.  
  14. Module Name:
  15.  
  16.     mfmt.c
  17.  
  18. Abstract:
  19.  
  20.     This program is designed to show how to access a physical floppy
  21.     disk using the Win32 API set.
  22.  
  23.     This program has two major functions.
  24.  
  25.         - It can be used to display the geometry of a disk
  26.  
  27.             mfmt -g a:
  28.  
  29.         - It can be used to produce a disk image, or to write a disk
  30.           image to a floppy.
  31.  
  32.             mfmt -c a: bootdisk         - produce a disk image of a:
  33.  
  34.             mfmt -c bootdisk a:         - make a: identical to bootdisk image
  35.  
  36.     This program is very very simple. Minimal error checking is done. It is
  37.     meant to provide an example of how to:
  38.  
  39.         - Open a physical disk
  40.  
  41.         - Read a disk's geometry
  42.  
  43.         - Perform a low level format operation
  44.  
  45.         - read and write physical sectors
  46.  
  47. --*/
  48.  
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include <windows.h>
  52. #include <winioctl.h>
  53. #include <string.h>
  54. #include <ctype.h>
  55. #include <memory.h>
  56.  
  57. DISK_GEOMETRY SupportedGeometry[20];
  58. DWORD SupportedGeometryCount;
  59.  
  60. BOOL
  61. GetDiskGeometry(
  62.     HANDLE hDisk,
  63.     PDISK_GEOMETRY lpGeometry
  64.     )
  65.  
  66. {
  67.     DWORD ReturnedByteCount;
  68.  
  69.     return DeviceIoControl(
  70.                 hDisk,
  71.                 IOCTL_DISK_GET_DRIVE_GEOMETRY,
  72.                 NULL,
  73.                 0,
  74.                 lpGeometry,
  75.                 sizeof(*lpGeometry),
  76.                 &ReturnedByteCount,
  77.                 NULL
  78.                 );
  79. }
  80.  
  81. DWORD
  82. GetSupportedGeometrys(
  83.     HANDLE hDisk
  84.     )
  85. {
  86.     DWORD ReturnedByteCount;
  87.     BOOL b;
  88.     DWORD NumberSupported;
  89.  
  90.     b = DeviceIoControl(
  91.                 hDisk,
  92.                 IOCTL_DISK_GET_MEDIA_TYPES,
  93.                 NULL,
  94.                 0,
  95.                 SupportedGeometry,
  96.                 sizeof(SupportedGeometry),
  97.                 &ReturnedByteCount,
  98.                 NULL
  99.                 );
  100.     if ( b ) {
  101.         NumberSupported = ReturnedByteCount / sizeof(DISK_GEOMETRY);
  102.         }
  103.     else {
  104.         NumberSupported = 0;
  105.         }
  106.     SupportedGeometryCount = NumberSupported;
  107.  
  108.     return NumberSupported;
  109. }
  110.  
  111. VOID
  112. PrintGeometry(
  113.     LPSTR lpDriveName,
  114.     PDISK_GEOMETRY lpGeometry
  115.     )
  116. {
  117.     LPSTR MediaType;
  118.  
  119.     if (lpDriveName) {
  120.         printf("Geometry for Drive %s\n",lpDriveName);
  121.         }
  122.  
  123.     switch ( lpGeometry->MediaType ) {
  124.         case F5_1Pt2_512:  MediaType = "5.25, 1.2MB,  512 bytes/sector";break;
  125.         case F3_1Pt44_512: MediaType = "3.5,  1.44MB, 512 bytes/sector";break;
  126.         case F3_2Pt88_512: MediaType = "3.5,  2.88MB, 512 bytes/sector";break;
  127.         case F3_20Pt8_512: MediaType = "3.5,  20.8MB, 512 bytes/sector";break;
  128.         case F3_720_512:   MediaType = "3.5,  720KB,  512 bytes/sector";break;
  129.         case F5_360_512:   MediaType = "5.25, 360KB,  512 bytes/sector";break;
  130.         case F5_320_512:   MediaType = "5.25, 320KB,  512 bytes/sector";break;
  131.         case F5_320_1024:  MediaType = "5.25, 320KB,  1024 bytes/sector";break;
  132.         case F5_180_512:   MediaType = "5.25, 180KB,  512 bytes/sector";break;
  133.         case F5_160_512:   MediaType = "5.25, 160KB,  512 bytes/sector";break;
  134.         case RemovableMedia: MediaType = "Removable media other than floppy";break;
  135.         case FixedMedia:   MediaType = "Fixed hard disk media";break;
  136.         default:           MediaType = "Unknown";break;
  137.     }
  138.     printf("    Media Type %s\n",MediaType);
  139.     printf("    Cylinders %d Tracks/Cylinder %d Sectors/Track %d\n",
  140.         lpGeometry->Cylinders.LowPart,
  141.         lpGeometry->TracksPerCylinder,
  142.         lpGeometry->SectorsPerTrack
  143.         );
  144. }
  145.  
  146. BOOL
  147. LowLevelFormat(
  148.     HANDLE hDisk,
  149.     PDISK_GEOMETRY lpGeometry
  150.     )
  151. {
  152.     FORMAT_PARAMETERS FormatParameters;
  153.     PBAD_TRACK_NUMBER lpBadTrack;
  154.     UINT i;
  155.     BOOL b;
  156.     DWORD ReturnedByteCount;
  157.  
  158.     FormatParameters.MediaType = lpGeometry->MediaType;
  159.     FormatParameters.StartHeadNumber = 0;
  160.     FormatParameters.EndHeadNumber = lpGeometry->TracksPerCylinder - 1;
  161.     lpBadTrack = (PBAD_TRACK_NUMBER) LocalAlloc(LMEM_ZEROINIT,lpGeometry->TracksPerCylinder*sizeof(*lpBadTrack));
  162.  
  163.     for (i = 0; i < lpGeometry->Cylinders.LowPart; i++) {
  164.  
  165.         FormatParameters.StartCylinderNumber = i;
  166.         FormatParameters.EndCylinderNumber = i;
  167.  
  168.         b = DeviceIoControl(
  169.                 hDisk,
  170.                 IOCTL_DISK_FORMAT_TRACKS,
  171.                 &FormatParameters,
  172.                 sizeof(FormatParameters),
  173.                 lpBadTrack,
  174.                 lpGeometry->TracksPerCylinder*sizeof(*lpBadTrack),
  175.                 &ReturnedByteCount,
  176.                 NULL
  177.                 );
  178.  
  179.         if (!b ) {
  180.             LocalFree(lpBadTrack);
  181.             return b;
  182.             }
  183.         }
  184.  
  185.     LocalFree(lpBadTrack);
  186.  
  187.     return TRUE;
  188. }
  189.  
  190. BOOL
  191. LockVolume(
  192.     HANDLE hDisk
  193.     )
  194. {
  195.     DWORD ReturnedByteCount;
  196.  
  197.     return DeviceIoControl(
  198.                 hDisk,
  199.                 FSCTL_LOCK_VOLUME,
  200.                 NULL,
  201.                 0,
  202.                 NULL,
  203.                 0,
  204.                 &ReturnedByteCount,
  205.                 NULL
  206.                 );
  207. }
  208.  
  209. BOOL
  210. UnlockVolume(
  211.     HANDLE hDisk
  212.     )
  213. {
  214.     DWORD ReturnedByteCount;
  215.  
  216.     return DeviceIoControl(
  217.                 hDisk,
  218.                 FSCTL_UNLOCK_VOLUME,
  219.                 NULL,
  220.                 0,
  221.                 NULL,
  222.                 0,
  223.                 &ReturnedByteCount,
  224.                 NULL
  225.                 );
  226. }
  227.  
  228. BOOL
  229. DismountVolume(
  230.     HANDLE hDisk
  231.     )
  232. {
  233.     DWORD ReturnedByteCount;
  234.  
  235.     return DeviceIoControl(
  236.                 hDisk,
  237.                 FSCTL_DISMOUNT_VOLUME,
  238.                 NULL,
  239.                 0,
  240.                 NULL,
  241.                 0,
  242.                 &ReturnedByteCount,
  243.                 NULL
  244.                 );
  245. }
  246.  
  247. DWORD
  248. _cdecl
  249. main(
  250.     int argc,
  251.     char *argv[],
  252.     char *envp[]
  253.     )
  254. {
  255.     char Drive[MAX_PATH];
  256.     HANDLE hDrive, hDiskImage;
  257.     DISK_GEOMETRY Geometry;
  258.     UINT i;
  259.     char c, *p;
  260.     LPSTR DriveName;
  261.     BOOL fUsage = TRUE;
  262.     BOOL fShowGeometry = FALSE;
  263.     BOOL fDiskImage = FALSE;
  264.     BOOL SourceIsDrive;
  265.     LPSTR Source, Destination, DiskImage;
  266.  
  267.     if ( argc > 1 ) {
  268.         fUsage = FALSE;
  269.         while (--argc > 0 ) {
  270.             p = *++argv;
  271.             if (*p == '/' || *p == '-') {
  272.                 while (c = *++p)
  273.                 switch (toupper( c )) {
  274.                 case '?':
  275.                     fUsage = TRUE;
  276.                     break;
  277.  
  278.                 case 'C':
  279.                     fDiskImage = TRUE;
  280.                     argc--, argv++;
  281.                     Source = *argv;
  282.                     argc--, argv++;
  283.                     Destination = *argv;
  284.                     break;
  285.  
  286.                 case 'G':
  287.                     argc--, argv++;
  288.                     if ( (DriveName = *argv ) && *DriveName && 
  289.                          isalpha(*DriveName) )
  290.                         fShowGeometry = TRUE;
  291.                     else
  292.                                                 {
  293.                         printf( "MFMT: Missing drive letter after -G\n" );
  294.                                     DriveName = NULL;
  295.                         fUsage = TRUE;
  296.                         }
  297.                             break;
  298.  
  299.                 default:
  300.                     printf("MFMT: Invalid switch - /%c\n", c );
  301.                     fUsage = TRUE;
  302.                     break;
  303.                     }
  304.                 }
  305.             }
  306.         }
  307.  
  308.     if ( fUsage ) {
  309.         printf("usage: MFMT switches \n" );
  310.         printf("            [-?] display this message\n" );
  311.         printf("            [-g drive] shows disk geometry\n" );
  312.         printf("            [-c source destination] produce diskimage\n" );
  313.         ExitProcess(1);
  314.         }
  315.  
  316.     if ( fShowGeometry ) {
  317.         sprintf(Drive,"\\\\.\\%s",DriveName);
  318.         hDrive = CreateFile(
  319.                     Drive,
  320.                     GENERIC_READ | GENERIC_WRITE,
  321.                     FILE_SHARE_READ|FILE_SHARE_WRITE,
  322.                     NULL,
  323.                     OPEN_EXISTING,
  324.                     0,
  325.                     NULL
  326.                     );
  327.         if ( hDrive == INVALID_HANDLE_VALUE ) {
  328.             printf("MFMT: Open %s failed %d\n",DriveName,GetLastError());
  329.             ExitProcess(1);
  330.             }
  331.  
  332.         if ( LockVolume(hDrive) == FALSE ) {
  333.             printf("MFMT:Locking volume %s failed %d\n", DriveName, GetLastError());
  334.             ExitProcess(1);
  335.             }
  336.  
  337.         if ( !GetDiskGeometry(hDrive,&Geometry) ) {
  338.             printf("MFMT: GetDiskGeometry %s failed %d\n",DriveName,GetLastError());
  339.             ExitProcess(1);
  340.             }
  341.         PrintGeometry(DriveName,&Geometry);
  342.  
  343.         if ( !GetSupportedGeometrys(hDrive) ) {
  344.             printf("MFMT: GetSupportedGeometrys %s failed %d\n",DriveName,GetLastError());
  345.             ExitProcess(1);
  346.             }
  347.         printf("\nDrive %s supports the following disk geometries\n",DriveName);
  348.  
  349.         for(i=0;i<SupportedGeometryCount;i++) {
  350.             printf("\n");
  351.             PrintGeometry(NULL,&SupportedGeometry[i]);
  352.             }
  353.  
  354.         printf("\n");
  355.         ExitProcess(0);
  356.         }
  357.  
  358.     if ( fDiskImage ) {
  359.         SourceIsDrive = FALSE;
  360.         if ( Source[strlen(Source)-1] == ':' ) {
  361.             SourceIsDrive = TRUE;
  362.             sprintf(Drive,"\\\\.\\%s",Source);
  363.             DriveName=Source;
  364.             DiskImage = Destination;
  365.             }
  366.         if ( Destination[strlen(Destination)-1] == ':' ) {
  367.             if ( SourceIsDrive ) {
  368.                 printf("MFMT: Source and Destination cannot both be drives\n");
  369.                 ExitProcess(1);
  370.                 }
  371.             SourceIsDrive = FALSE;
  372.             sprintf(Drive,"\\\\.\\%s",Destination);
  373.             DriveName=Destination;
  374.             DiskImage = Source;
  375.             }
  376.         else {
  377.             if ( !SourceIsDrive ) {
  378.                 printf("MFMT: Either Source or Destination must be a drive\n");
  379.                 ExitProcess(1);
  380.                 }
  381.             }
  382.  
  383.         //
  384.         // Open and Lock the drive
  385.         //
  386.  
  387.         hDrive = CreateFile(
  388.                     Drive,
  389.                     GENERIC_READ | GENERIC_WRITE,
  390.                     FILE_SHARE_READ|FILE_SHARE_WRITE,
  391.                     NULL,
  392.                     OPEN_EXISTING,
  393.                     0,
  394.                     NULL
  395.                     );
  396.         if ( hDrive == INVALID_HANDLE_VALUE ) {
  397.             printf("MFMT: Open %s failed %d\n",DriveName,GetLastError());
  398.             ExitProcess(1);
  399.             }
  400.         if ( LockVolume(hDrive) == FALSE ) {
  401.             printf("MFMT: LockVolume %s failed %d\n",DriveName,GetLastError());
  402.             ExitProcess(1);
  403.             }
  404.  
  405.         if ( !GetDiskGeometry(hDrive,&Geometry) ) {
  406.             printf("MFMT: GetDiskGeometry %s failed %d\n",DriveName,GetLastError());
  407.             ExitProcess(1);
  408.             }
  409.  
  410.         if ( !GetSupportedGeometrys(hDrive) ) {
  411.             printf("MFMT: GetSupportedGeometrys %s failed %d\n",DriveName,GetLastError());
  412.             ExitProcess(1);
  413.             }
  414.  
  415.         //
  416.         // Open the disk image file
  417.         //
  418.  
  419.         hDiskImage = CreateFile(
  420.                         DiskImage,
  421.                         GENERIC_READ | GENERIC_WRITE,
  422.                         0,
  423.                         NULL,
  424.                         SourceIsDrive ? CREATE_ALWAYS : OPEN_EXISTING,
  425.                         0,
  426.                         NULL
  427.                         );
  428.         if ( hDiskImage == INVALID_HANDLE_VALUE ) {
  429.             printf("MFMT: Open %s failed %d\n",DiskImage,GetLastError());
  430.             ExitProcess(1);
  431.             }
  432.  
  433.         //
  434.         // Now do the copy
  435.         //
  436.         {
  437.             LPVOID IoBuffer;
  438.             BOOL b;
  439.             DWORD BytesRead, BytesWritten;
  440.             DWORD FileSize;
  441.             DWORD VirtBufSize;
  442.             DWORD NumBufs;
  443.  
  444.             //
  445.             // If we are copying from floppy to file, just do the copy
  446.             // Otherwise, we might have to format the floppy first
  447.             //
  448.  
  449.             if ( SourceIsDrive ) {
  450.  
  451.                 //
  452.                 // Device reads must be sector aligned. VirtualAlloc will
  453.                 // garuntee alignment
  454.                 //
  455.  
  456.                 NumBufs = Geometry.Cylinders.LowPart;
  457.                 VirtBufSize =  Geometry.TracksPerCylinder *
  458.                                Geometry.SectorsPerTrack *
  459.                                Geometry.BytesPerSector;
  460.  
  461.                 IoBuffer = VirtualAlloc(NULL,VirtBufSize,MEM_COMMIT,PAGE_READWRITE);
  462.  
  463.                 if ( !IoBuffer ) {
  464.                     printf("MFMT: Buffer Allocation Failed\n");
  465.                     ExitProcess(1);
  466.                     }
  467.  
  468.                 for ( ;NumBufs > 0; NumBufs-- )
  469.                     {
  470.                     b = ReadFile(hDrive,IoBuffer, VirtBufSize, &BytesRead, NULL);
  471.                     if (b && BytesRead){
  472.                         b = WriteFile(hDiskImage,IoBuffer, BytesRead, &BytesWritten, NULL);
  473.                         if ( !b || ( BytesRead != BytesWritten ) ) {
  474.                             printf("MFMT: Fatal Write Error %d\n",GetLastError());
  475.                             ExitProcess(1);
  476.                             }
  477.                         }
  478.                     else {
  479.                         printf("MFMT: Fatal Read Error %d\n",GetLastError());
  480.                         ExitProcess(1);
  481.                         }
  482.                     }
  483.                 }
  484.             else {
  485.  
  486.                 //
  487.                 // Check to see if the image will fit on the floppy. If it
  488.                 // will, then LowLevelFormat the floppy and press on
  489.                 //
  490.  
  491.                 FileSize = GetFileSize(hDiskImage,NULL);
  492.  
  493.                 b = FALSE;
  494.                 for(i=0;i<SupportedGeometryCount;i++) {
  495.                     NumBufs = SupportedGeometry[i].Cylinders.LowPart;
  496.                     VirtBufSize =  SupportedGeometry[i].TracksPerCylinder *
  497.                                    SupportedGeometry[i].SectorsPerTrack *
  498.                                    SupportedGeometry[i].BytesPerSector;
  499.                     if ( VirtBufSize*NumBufs >= FileSize ) {
  500.  
  501.                         IoBuffer = VirtualAlloc(NULL,VirtBufSize,MEM_COMMIT,PAGE_READWRITE);
  502.  
  503.                         if ( !IoBuffer ) {
  504.                             printf("MFMT: Buffer Allocation Failed\n");
  505.                             ExitProcess(1);
  506.                             }
  507.  
  508.                         //
  509.                         // Format the floppy
  510.                         //
  511.  
  512.                         LowLevelFormat(hDrive,&SupportedGeometry[i]);
  513.  
  514.                         for ( ;NumBufs > 0; NumBufs-- )
  515.                             {
  516.                             b = ReadFile(hDiskImage,IoBuffer, VirtBufSize, &BytesRead, NULL);
  517.                             if (b && BytesRead){
  518.                                 b = WriteFile(hDrive,IoBuffer, BytesRead, &BytesWritten, NULL);
  519.                                 if ( !b || ( BytesRead != BytesWritten ) ) {
  520.                                     printf("MFMT: Fatal Write Error %d\n",GetLastError());
  521.                                     ExitProcess(1);
  522.                                     }
  523.                                 }
  524.                             else {
  525.                                 printf("MFMT: Fatal Read Error %d\n",GetLastError());
  526.                                 ExitProcess(1);
  527.                                 }
  528.                             }
  529.                         b = TRUE;
  530.                         break;
  531.                         }
  532.                     }
  533.  
  534.                 if ( !b ) {
  535.                     printf("MFMT: FileSize %d is not supported on drive %s\n",FileSize,DriveName);
  536.                     ExitProcess(1);
  537.                     }
  538.                 }
  539.         }
  540.  
  541.         //
  542.         // Dismounting forces the filesystem to re-evaluate the media id
  543.         // and geometry. This is the same as popping the floppy in and out
  544.         // of the disk drive
  545.         //
  546.  
  547.         DismountVolume(hDrive);
  548.         UnlockVolume(hDrive);
  549.  
  550.         ExitProcess(0);
  551.         }
  552.     return (0);
  553. }
  554.