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.

555 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. VolInfo.c
  5. Abstract:
  6. This module implements the volume information routines for Raw called by
  7. the dispatch driver.
  8. Author:
  9. Gary Kimura [GaryKi] 28-Dec-1989
  10. Revision History:
  11. --*/
  12. #include "RawProcs.h"
  13. NTSTATUS
  14. RawQueryFsVolumeInfo (
  15. IN PVCB Vcb,
  16. IN PFILE_FS_VOLUME_INFORMATION Buffer,
  17. IN OUT PULONG Length
  18. );
  19. NTSTATUS
  20. RawQueryFsSizeInfo (
  21. IN PVCB Vcb,
  22. IN PFILE_FS_SIZE_INFORMATION Buffer,
  23. IN OUT PULONG Length
  24. );
  25. NTSTATUS
  26. RawQueryFsDeviceInfo (
  27. IN PVCB Vcb,
  28. IN PFILE_FS_DEVICE_INFORMATION Buffer,
  29. IN OUT PULONG Length
  30. );
  31. NTSTATUS
  32. RawQueryFsAttributeInfo (
  33. IN PVCB Vcb,
  34. IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
  35. IN OUT PULONG Length
  36. );
  37. #ifdef ALLOC_PRAGMA
  38. #pragma alloc_text(PAGE, RawQueryVolumeInformation)
  39. #pragma alloc_text(PAGE, RawQueryFsVolumeInfo)
  40. #pragma alloc_text(PAGE, RawQueryFsSizeInfo)
  41. #pragma alloc_text(PAGE, RawQueryFsDeviceInfo)
  42. #pragma alloc_text(PAGE, RawQueryFsAttributeInfo)
  43. #endif
  44. NTSTATUS
  45. RawQueryVolumeInformation (
  46. IN PVCB Vcb,
  47. IN PIRP Irp,
  48. IN PIO_STACK_LOCATION IrpSp
  49. )
  50. /*++
  51. Routine Description:
  52. This routine implements the NtQueryVolumeInformation API call.
  53. Arguments:
  54. Vcb - Supplies the volume being queried.
  55. Irp - Supplies the Irp being processed.
  56. IrpSp - Supplies parameters describing the read
  57. Return Value:
  58. NTSTATUS - The status for the Irp.
  59. --*/
  60. {
  61. NTSTATUS Status;
  62. ULONG Length;
  63. FS_INFORMATION_CLASS FsInformationClass;
  64. PVOID Buffer;
  65. PAGED_CODE();
  66. //
  67. // Reference our input parameters to make things easier
  68. //
  69. Length = IrpSp->Parameters.QueryVolume.Length;
  70. FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
  71. Buffer = Irp->AssociatedIrp.SystemBuffer;
  72. //
  73. // Based on the information class we'll do different actions. Each
  74. // of the procedures that we're calling fills up the output buffer
  75. // if possible and returns true if it successfully filled the buffer
  76. // and false if it couldn't wait for any I/O to complete.
  77. //
  78. switch (FsInformationClass) {
  79. case FileFsVolumeInformation:
  80. Status = RawQueryFsVolumeInfo( Vcb, Buffer, &Length );
  81. break;
  82. case FileFsSizeInformation:
  83. Status = RawQueryFsSizeInfo( Vcb, Buffer, &Length );
  84. break;
  85. case FileFsDeviceInformation:
  86. Status = RawQueryFsDeviceInfo( Vcb, Buffer, &Length );
  87. break;
  88. case FileFsAttributeInformation:
  89. Status = RawQueryFsAttributeInfo( Vcb, Buffer, &Length );
  90. break;
  91. default:
  92. Status = STATUS_INVALID_PARAMETER;
  93. break;
  94. }
  95. //
  96. // Set the information field to the number of bytes actually filled in,
  97. // and complete the request.
  98. //
  99. Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
  100. RawCompleteRequest( Irp, Status );
  101. return Status;
  102. }
  103. //
  104. // Internal support routine
  105. //
  106. NTSTATUS
  107. RawQueryFsVolumeInfo (
  108. IN PVCB Vcb,
  109. IN PFILE_FS_VOLUME_INFORMATION Buffer,
  110. IN OUT PULONG Length
  111. )
  112. /*++
  113. Routine Description:
  114. This routine implements the query volume info call
  115. Arguments:
  116. Vcb - Supplies the Vcb being queried
  117. Buffer - Supplies a pointer to the output buffer where the information
  118. is to be returned
  119. Length - Supplies the length of the buffer in byte. This variable
  120. upon return recieves the remaining bytes free in the buffer
  121. Return Value:
  122. NTSTATUS - Returns the status for the query
  123. --*/
  124. {
  125. PAGED_CODE();
  126. //
  127. // Zero out the buffer, then extract and fill up the non zero fields.
  128. //
  129. RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION) );
  130. Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
  131. Buffer->SupportsObjects = FALSE;
  132. Buffer->VolumeLabelLength = 0;
  133. *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
  134. //
  135. // Set our status and return to our caller
  136. //
  137. return STATUS_SUCCESS;
  138. }
  139. //
  140. // Internal support routine
  141. //
  142. NTSTATUS
  143. RawQueryFsSizeInfo (
  144. IN PVCB Vcb,
  145. IN PFILE_FS_SIZE_INFORMATION Buffer,
  146. IN OUT PULONG Length
  147. )
  148. /*++
  149. Routine Description:
  150. This routine implements the query volume size call
  151. Arguments:
  152. Vcb - Supplies the Vcb being queried
  153. Buffer - Supplies a pointer to the output buffer where the information
  154. is to be returned
  155. Length - Supplies the length of the buffer in byte. This variable
  156. upon return recieves the remaining bytes free in the buffer
  157. Return Value:
  158. Status - Returns the status for the query
  159. --*/
  160. {
  161. PIRP Irp;
  162. KEVENT Event;
  163. NTSTATUS Status;
  164. IO_STATUS_BLOCK Iosb;
  165. PDEVICE_OBJECT RealDevice;
  166. DISK_GEOMETRY DiskGeometry;
  167. PARTITION_INFORMATION_EX PartitionInformation;
  168. BOOLEAN DriveIsPartitioned;
  169. PAGED_CODE();
  170. //
  171. // Make sure the buffer is large enough
  172. //
  173. if (*Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
  174. return STATUS_BUFFER_OVERFLOW;
  175. }
  176. RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) );
  177. //
  178. // Prepare for our device control below. The device drivers only
  179. // have to copy geometry and partition info from in-memory strucures,
  180. // so it is OK to make these calls even when we can't wait.
  181. //
  182. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  183. RealDevice = Vcb->Vpb->RealDevice;
  184. //
  185. // Query the disk geometry
  186. //
  187. Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_GEOMETRY,
  188. RealDevice,
  189. NULL,
  190. 0,
  191. &DiskGeometry,
  192. sizeof(DISK_GEOMETRY),
  193. FALSE,
  194. &Event,
  195. &Iosb );
  196. if ( Irp == NULL ) {
  197. return STATUS_INSUFFICIENT_RESOURCES;
  198. }
  199. if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
  200. (VOID) KeWaitForSingleObject( &Event,
  201. Executive,
  202. KernelMode,
  203. FALSE,
  204. (PLARGE_INTEGER)NULL );
  205. Status = Iosb.Status;
  206. }
  207. //
  208. // If this call didn't succeed, the drive hasn't even been low-level
  209. // formatted, and thus geometry information is undefined.
  210. //
  211. if (!NT_SUCCESS( Status )) {
  212. *Length = 0;
  213. return Status;
  214. }
  215. //
  216. // See if we have to check the partition information (floppy disks are
  217. // the only type that can't have partitions )
  218. //
  219. if ( FlagOn( RealDevice->Characteristics, FILE_FLOPPY_DISKETTE )) {
  220. DriveIsPartitioned = FALSE;
  221. } else {
  222. //
  223. // Query the partition table
  224. //
  225. KeResetEvent( &Event );
  226. Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO_EX,
  227. RealDevice,
  228. NULL,
  229. 0,
  230. &PartitionInformation,
  231. sizeof(PARTITION_INFORMATION_EX),
  232. FALSE,
  233. &Event,
  234. &Iosb );
  235. if ( Irp == NULL ) {
  236. return STATUS_INSUFFICIENT_RESOURCES;
  237. }
  238. if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
  239. (VOID) KeWaitForSingleObject( &Event,
  240. Executive,
  241. KernelMode,
  242. FALSE,
  243. (PLARGE_INTEGER)NULL );
  244. Status = Iosb.Status;
  245. }
  246. //
  247. // If we get back invalid device request, the disk is not partitioned
  248. //
  249. if ( !NT_SUCCESS (Status) ) {
  250. DriveIsPartitioned = FALSE;
  251. } else {
  252. DriveIsPartitioned = TRUE;
  253. }
  254. }
  255. //
  256. // Set the output buffer
  257. //
  258. Buffer->BytesPerSector = DiskGeometry.BytesPerSector;
  259. Buffer->SectorsPerAllocationUnit = 1;
  260. //
  261. // Now, based on whether the disk is partitioned, compute the
  262. // total number of sectors on this disk.
  263. //
  264. Buffer->TotalAllocationUnits =
  265. Buffer->AvailableAllocationUnits = ( DriveIsPartitioned == TRUE ) ?
  266. RtlExtendedLargeIntegerDivide( PartitionInformation.PartitionLength,
  267. DiskGeometry.BytesPerSector,
  268. NULL )
  269. :
  270. RtlExtendedIntegerMultiply( DiskGeometry.Cylinders,
  271. DiskGeometry.TracksPerCylinder *
  272. DiskGeometry.SectorsPerTrack );
  273. //
  274. // Adjust the length variable
  275. //
  276. *Length -= sizeof(FILE_FS_SIZE_INFORMATION);
  277. //
  278. // And return success to our caller
  279. //
  280. return STATUS_SUCCESS;
  281. }
  282. //
  283. // Internal support routine
  284. //
  285. NTSTATUS
  286. RawQueryFsDeviceInfo (
  287. IN PVCB Vcb,
  288. IN PFILE_FS_DEVICE_INFORMATION Buffer,
  289. IN OUT PULONG Length
  290. )
  291. /*++
  292. Routine Description:
  293. This routine implements the query volume device call
  294. Arguments:
  295. Vcb - Supplies the Vcb being queried
  296. Buffer - Supplies a pointer to the output buffer where the information
  297. is to be returned
  298. Length - Supplies the length of the buffer in byte. This variable
  299. upon return recieves the remaining bytes free in the buffer
  300. Return Value:
  301. Status - Returns the status for the query
  302. --*/
  303. {
  304. PAGED_CODE();
  305. //
  306. // Make sure the buffer is large enough
  307. //
  308. if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
  309. return STATUS_BUFFER_OVERFLOW;
  310. }
  311. RtlZeroMemory( Buffer, sizeof(FILE_FS_DEVICE_INFORMATION) );
  312. //
  313. // Set the output buffer
  314. //
  315. Buffer->DeviceType = FILE_DEVICE_DISK;
  316. Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
  317. //
  318. // Adjust the length variable
  319. //
  320. *Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
  321. //
  322. // And return success to our caller
  323. //
  324. return STATUS_SUCCESS;
  325. }
  326. //
  327. // Internal support routine
  328. //
  329. NTSTATUS
  330. RawQueryFsAttributeInfo (
  331. IN PVCB Vcb,
  332. IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
  333. IN OUT PULONG Length
  334. )
  335. /*++
  336. Routine Description:
  337. This routine implements the query volume attribute call
  338. Arguments:
  339. Vcb - Supplies the Vcb being queried
  340. Buffer - Supplies a pointer to the output buffer where the information
  341. is to be returned
  342. Length - Supplies the length of the buffer in byte. This variable
  343. upon return recieves the remaining bytes free in the buffer
  344. Return Value:
  345. Status - Returns the status for the query
  346. --*/
  347. {
  348. ULONG LengthUsed;
  349. UNREFERENCED_PARAMETER( Vcb );
  350. PAGED_CODE();
  351. //
  352. // Check if the buffer we're given is long enough to contain "Raw"
  353. //
  354. LengthUsed = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]) + 6;
  355. if (*Length < LengthUsed) {
  356. return STATUS_BUFFER_OVERFLOW;
  357. }
  358. //
  359. // Set the output buffer
  360. //
  361. Buffer->FileSystemAttributes = 0;
  362. Buffer->MaximumComponentNameLength = 0;
  363. Buffer->FileSystemNameLength = 6;
  364. RtlCopyMemory( &Buffer->FileSystemName[0], L"RAW", 6 );
  365. //
  366. // Adjust the length variable
  367. //
  368. *Length -= LengthUsed;
  369. //
  370. // And return success to our caller
  371. //
  372. return STATUS_SUCCESS;
  373. }