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.

353 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fat_rec.c
  5. Abstract:
  6. This module contains the mini-file system recognizer for FAT.
  7. Author:
  8. Darryl E. Havens (darrylh) 8-dec-1992
  9. Environment:
  10. Kernel mode, local to I/O system
  11. Revision History:
  12. --*/
  13. #include "fs_rec.h"
  14. #include "fat_rec.h"
  15. //
  16. // The local debug trace level
  17. //
  18. #define Dbg (FSREC_DEBUG_LEVEL_FAT)
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE,FatRecFsControl)
  21. #pragma alloc_text(PAGE,IsFatVolume)
  22. #pragma alloc_text(PAGE,UnpackBiosParameterBlock)
  23. #endif // ALLOC_PRAGMA
  24. NTSTATUS
  25. FatRecFsControl(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp
  28. )
  29. /*++
  30. Routine Description:
  31. This function performs the mount and driver reload functions for this mini-
  32. file system recognizer driver.
  33. Arguments:
  34. DeviceObject - Pointer to this driver's device object.
  35. Irp - Pointer to the I/O Request Packet (IRP) representing the function to
  36. be performed.
  37. Return Value:
  38. The function value is the final status of the operation.
  39. --*/
  40. {
  41. NTSTATUS status;
  42. PIO_STACK_LOCATION irpSp;
  43. PDEVICE_EXTENSION deviceExtension;
  44. PDEVICE_OBJECT targetDevice;
  45. PPACKED_BOOT_SECTOR buffer;
  46. LARGE_INTEGER byteOffset;
  47. UNICODE_STRING driverName;
  48. ULONG bytesPerSector;
  49. BOOLEAN isDeviceFailure = FALSE;
  50. PAGED_CODE();
  51. //
  52. // Begin by determining what function that is to be performed.
  53. //
  54. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  55. irpSp = IoGetCurrentIrpStackLocation( Irp );
  56. switch ( irpSp->MinorFunction ) {
  57. case IRP_MN_MOUNT_VOLUME:
  58. //
  59. // Attempt to mount a volume: Determine whether or not the volume in
  60. // question is a FAT volume and, if so, let the I/O system know that it
  61. // is by returning a special status code so that this driver can get
  62. // called back to load the FAT file system.
  63. //
  64. status = STATUS_UNRECOGNIZED_VOLUME;
  65. //
  66. // Attempt to determine whether or not the target volume being mounted
  67. // is a FAT volume. Note that if an error occurs, and this is a floppy
  68. // drive, and the error occurred on the actual read from the device,
  69. // then the FAT file system will actually be loaded to handle the
  70. // problem since this driver is a place holder and does not need to
  71. // know all of the protocols for handling floppy errors.
  72. //
  73. targetDevice = irpSp->Parameters.MountVolume.DeviceObject;
  74. //
  75. // First retrieve the sector size for this media.
  76. //
  77. if (FsRecGetDeviceSectorSize( targetDevice,
  78. &bytesPerSector )) {
  79. byteOffset.QuadPart = 0;
  80. buffer = NULL;
  81. if (FsRecReadBlock( targetDevice,
  82. &byteOffset,
  83. 512,
  84. bytesPerSector,
  85. &buffer,
  86. &isDeviceFailure ) &&
  87. IsFatVolume( buffer )) {
  88. status = STATUS_FS_DRIVER_REQUIRED;
  89. }
  90. if (buffer != NULL) {
  91. ExFreePool( buffer );
  92. }
  93. } else {
  94. //
  95. // Devices that can't get us this much ...
  96. //
  97. isDeviceFailure = TRUE;
  98. }
  99. //
  100. // See if we should make the real filesystem take a shot at a wacky floppy.
  101. //
  102. if (isDeviceFailure) {
  103. if (targetDevice->Characteristics & FILE_FLOPPY_DISKETTE) {
  104. status = STATUS_FS_DRIVER_REQUIRED;
  105. }
  106. }
  107. break;
  108. case IRP_MN_LOAD_FILE_SYSTEM:
  109. status = FsRecLoadFileSystem( DeviceObject,
  110. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Fastfat" );
  111. break;
  112. default:
  113. status = STATUS_INVALID_DEVICE_REQUEST;
  114. }
  115. //
  116. // Finally, complete the request and return the same status code to the
  117. // caller.
  118. //
  119. Irp->IoStatus.Status = status;
  120. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  121. return status;
  122. }
  123. BOOLEAN
  124. IsFatVolume(
  125. IN PPACKED_BOOT_SECTOR Buffer
  126. )
  127. /*++
  128. Routine Description:
  129. This routine looks at the buffer passed in which contains the FAT boot
  130. sector and determines whether or not it represents an actual FAT boot
  131. sector.
  132. Arguments:
  133. Buffer - Pointer to buffer containing potential boot block.
  134. Return Value:
  135. The function returns TRUE if the buffer contains a recognizable FAT boot
  136. sector, otherwise it returns FALSE.
  137. --*/
  138. {
  139. BIOS_PARAMETER_BLOCK bios;
  140. BOOLEAN result;
  141. PAGED_CODE();
  142. //
  143. // Begin by unpacking the Bios Parameter Block that is packed in the boot
  144. // sector so that it can be examined without incurring alignment faults.
  145. //
  146. UnpackBiosParameterBlock( &Buffer->PackedBpb, &bios );
  147. //
  148. // Assume that the sector represents a FAT boot block and then determine
  149. // whether or not it really does.
  150. //
  151. result = TRUE;
  152. if (bios.Sectors) {
  153. bios.LargeSectors = 0;
  154. }
  155. // FMR Jul.11.1994 NaokiM - Fujitsu -
  156. // FMR boot sector has 'IPL1' string at the beginnig.
  157. if (Buffer->Jump[0] != 0x49 && /* FMR */
  158. Buffer->Jump[0] != 0xe9 &&
  159. Buffer->Jump[0] != 0xeb) {
  160. result = FALSE;
  161. // FMR Jul.11.1994 NaokiM - Fujitsu -
  162. // Sector size of FMR partition is 2048.
  163. } else if (bios.BytesPerSector != 128 &&
  164. bios.BytesPerSector != 256 &&
  165. bios.BytesPerSector != 512 &&
  166. bios.BytesPerSector != 1024 &&
  167. bios.BytesPerSector != 2048 && /* FMR */
  168. bios.BytesPerSector != 4096) {
  169. result = FALSE;
  170. } else if (bios.SectorsPerCluster != 1 &&
  171. bios.SectorsPerCluster != 2 &&
  172. bios.SectorsPerCluster != 4 &&
  173. bios.SectorsPerCluster != 8 &&
  174. bios.SectorsPerCluster != 16 &&
  175. bios.SectorsPerCluster != 32 &&
  176. bios.SectorsPerCluster != 64 &&
  177. bios.SectorsPerCluster != 128) {
  178. result = FALSE;
  179. } else if (!bios.ReservedSectors) {
  180. result = FALSE;
  181. } else if (!bios.Fats) {
  182. result = FALSE;
  183. //
  184. // Prior to DOS 3.2 might contains value in both of Sectors and
  185. // Sectors Large.
  186. //
  187. } else if (!bios.Sectors && !bios.LargeSectors) {
  188. result = FALSE;
  189. // FMR Jul.11.1994 NaokiM - Fujitsu -
  190. // 1. Media descriptor of FMR partitions is 0xfa.
  191. // 2. Media descriptor of partitions formated by FMR OS/2 is 0x00.
  192. // 3. Media descriptor of floppy disks formated by FMR DOS is 0x01.
  193. } else if (bios.Media != 0x00 && /* FMR */
  194. bios.Media != 0x01 && /* FMR */
  195. bios.Media != 0xf0 &&
  196. bios.Media != 0xf8 &&
  197. bios.Media != 0xf9 &&
  198. bios.Media != 0xfa && /* FMR */
  199. bios.Media != 0xfb &&
  200. bios.Media != 0xfc &&
  201. bios.Media != 0xfd &&
  202. bios.Media != 0xfe &&
  203. bios.Media != 0xff) {
  204. result = FALSE;
  205. } else if (bios.SectorsPerFat != 0 && bios.RootEntries == 0) {
  206. result = FALSE;
  207. }
  208. return result;
  209. }
  210. VOID
  211. UnpackBiosParameterBlock(
  212. IN PPACKED_BIOS_PARAMETER_BLOCK Bios,
  213. OUT PBIOS_PARAMETER_BLOCK UnpackedBios
  214. )
  215. /*++
  216. Routine Description:
  217. This routine copies a packed Bios Parameter Block to an unpacked Bios
  218. Parameter Block.
  219. Arguments:
  220. Bios - Pointer to the packed Bios Parameter Block.
  221. UnpackedBios - Pointer to the unpacked Bios Parameter Block.
  222. Return Value:
  223. None.
  224. --*/
  225. {
  226. PAGED_CODE();
  227. //
  228. // Unpack the Bios Parameter Block.
  229. //
  230. CopyUchar2( &UnpackedBios->BytesPerSector, &Bios->BytesPerSector[0] );
  231. CopyUchar2( &UnpackedBios->BytesPerSector, &Bios->BytesPerSector[0] );
  232. CopyUchar1( &UnpackedBios->SectorsPerCluster, &Bios->SectorsPerCluster[0] );
  233. CopyUchar2( &UnpackedBios->ReservedSectors, &Bios->ReservedSectors[0] );
  234. CopyUchar1( &UnpackedBios->Fats, &Bios->Fats[0] );
  235. CopyUchar2( &UnpackedBios->RootEntries, &Bios->RootEntries[0] );
  236. CopyUchar2( &UnpackedBios->Sectors, &Bios->Sectors[0] );
  237. CopyUchar1( &UnpackedBios->Media, &Bios->Media[0] );
  238. CopyUchar2( &UnpackedBios->SectorsPerFat, &Bios->SectorsPerFat[0] );
  239. CopyUchar2( &UnpackedBios->SectorsPerTrack, &Bios->SectorsPerTrack[0] );
  240. CopyUchar2( &UnpackedBios->Heads, &Bios->Heads[0] );
  241. CopyUchar4( &UnpackedBios->HiddenSectors, &Bios->HiddenSectors[0] );
  242. CopyUchar4( &UnpackedBios->LargeSectors, &Bios->LargeSectors[0] );
  243. }