Source code of Windows XP (NT5)
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.

524 lines
14 KiB

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