Leaked source code of windows server 2003
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.

596 lines
14 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 PartitionInformation;
  168. GET_LENGTH_INFORMATION GetLengthInformation;
  169. BOOLEAN DriveIsPartitioned;
  170. PAGED_CODE();
  171. //
  172. // Make sure the buffer is large enough
  173. //
  174. if (*Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
  175. return STATUS_BUFFER_OVERFLOW;
  176. }
  177. RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) );
  178. //
  179. // Prepare for our device control below. The device drivers only
  180. // have to copy geometry and partition info from in-memory strucures,
  181. // so it is OK to make these calls even when we can't wait.
  182. //
  183. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  184. RealDevice = Vcb->Vpb->RealDevice;
  185. //
  186. // Query the disk geometry
  187. //
  188. Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_GEOMETRY,
  189. RealDevice,
  190. NULL,
  191. 0,
  192. &DiskGeometry,
  193. sizeof(DISK_GEOMETRY),
  194. FALSE,
  195. &Event,
  196. &Iosb );
  197. if ( Irp == NULL ) {
  198. return STATUS_INSUFFICIENT_RESOURCES;
  199. }
  200. if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
  201. (VOID) KeWaitForSingleObject( &Event,
  202. Executive,
  203. KernelMode,
  204. FALSE,
  205. (PLARGE_INTEGER)NULL );
  206. Status = Iosb.Status;
  207. }
  208. //
  209. // If this call didn't succeed, the drive hasn't even been low-level
  210. // formatted, and thus geometry information is undefined.
  211. //
  212. if (!NT_SUCCESS( Status )) {
  213. *Length = 0;
  214. return Status;
  215. }
  216. //
  217. // See if we have to check the partition information (floppy disks are
  218. // the only type that can't have partitions )
  219. //
  220. if ( FlagOn( RealDevice->Characteristics, FILE_FLOPPY_DISKETTE )) {
  221. DriveIsPartitioned = FALSE;
  222. PartitionInformation.PartitionLength.QuadPart = 0;
  223. } else {
  224. //
  225. // Query the length info.
  226. //
  227. KeResetEvent( &Event );
  228. Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_LENGTH_INFO,
  229. RealDevice,
  230. NULL,
  231. 0,
  232. &GetLengthInformation,
  233. sizeof(GET_LENGTH_INFORMATION),
  234. FALSE,
  235. &Event,
  236. &Iosb );
  237. if ( Irp == NULL ) {
  238. return STATUS_INSUFFICIENT_RESOURCES;
  239. }
  240. if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
  241. (VOID) KeWaitForSingleObject( &Event,
  242. Executive,
  243. KernelMode,
  244. FALSE,
  245. (PLARGE_INTEGER)NULL );
  246. Status = Iosb.Status;
  247. }
  248. PartitionInformation.PartitionLength = GetLengthInformation.Length;
  249. if ( !NT_SUCCESS (Status) ) {
  250. //
  251. // Query the partition table
  252. //
  253. KeResetEvent( &Event );
  254. Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO,
  255. RealDevice,
  256. NULL,
  257. 0,
  258. &PartitionInformation,
  259. sizeof(PARTITION_INFORMATION),
  260. FALSE,
  261. &Event,
  262. &Iosb );
  263. if ( Irp == NULL ) {
  264. return STATUS_INSUFFICIENT_RESOURCES;
  265. }
  266. if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
  267. (VOID) KeWaitForSingleObject( &Event,
  268. Executive,
  269. KernelMode,
  270. FALSE,
  271. (PLARGE_INTEGER)NULL );
  272. Status = Iosb.Status;
  273. }
  274. //
  275. // If we get back invalid device request, the disk is not partitioned
  276. //
  277. if ( !NT_SUCCESS (Status) ) {
  278. DriveIsPartitioned = FALSE;
  279. } else {
  280. DriveIsPartitioned = TRUE;
  281. }
  282. } else {
  283. DriveIsPartitioned = TRUE;
  284. }
  285. }
  286. //
  287. // Set the output buffer
  288. //
  289. Buffer->BytesPerSector = DiskGeometry.BytesPerSector;
  290. Buffer->SectorsPerAllocationUnit = 1;
  291. //
  292. // Now, based on whether the disk is partitioned, compute the
  293. // total number of sectors on this disk.
  294. //
  295. Buffer->TotalAllocationUnits =
  296. Buffer->AvailableAllocationUnits = ( DriveIsPartitioned == TRUE ) ?
  297. RtlExtendedLargeIntegerDivide( PartitionInformation.PartitionLength,
  298. DiskGeometry.BytesPerSector,
  299. NULL )
  300. :
  301. RtlExtendedIntegerMultiply( DiskGeometry.Cylinders,
  302. DiskGeometry.TracksPerCylinder *
  303. DiskGeometry.SectorsPerTrack );
  304. //
  305. // Adjust the length variable
  306. //
  307. *Length -= sizeof(FILE_FS_SIZE_INFORMATION);
  308. //
  309. // And return success to our caller
  310. //
  311. return STATUS_SUCCESS;
  312. }
  313. //
  314. // Internal support routine
  315. //
  316. NTSTATUS
  317. RawQueryFsDeviceInfo (
  318. IN PVCB Vcb,
  319. IN PFILE_FS_DEVICE_INFORMATION Buffer,
  320. IN OUT PULONG Length
  321. )
  322. /*++
  323. Routine Description:
  324. This routine implements the query volume device call
  325. Arguments:
  326. Vcb - Supplies the Vcb being queried
  327. Buffer - Supplies a pointer to the output buffer where the information
  328. is to be returned
  329. Length - Supplies the length of the buffer in byte. This variable
  330. upon return recieves the remaining bytes free in the buffer
  331. Return Value:
  332. Status - Returns the status for the query
  333. --*/
  334. {
  335. PAGED_CODE();
  336. //
  337. // Make sure the buffer is large enough
  338. //
  339. if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
  340. return STATUS_BUFFER_OVERFLOW;
  341. }
  342. RtlZeroMemory( Buffer, sizeof(FILE_FS_DEVICE_INFORMATION) );
  343. //
  344. // Set the output buffer
  345. //
  346. Buffer->DeviceType = FILE_DEVICE_DISK;
  347. Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
  348. //
  349. // Adjust the length variable
  350. //
  351. *Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
  352. //
  353. // And return success to our caller
  354. //
  355. return STATUS_SUCCESS;
  356. }
  357. //
  358. // Internal support routine
  359. //
  360. NTSTATUS
  361. RawQueryFsAttributeInfo (
  362. IN PVCB Vcb,
  363. IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
  364. IN OUT PULONG Length
  365. )
  366. /*++
  367. Routine Description:
  368. This routine implements the query volume attribute call
  369. Arguments:
  370. Vcb - Supplies the Vcb being queried
  371. Buffer - Supplies a pointer to the output buffer where the information
  372. is to be returned
  373. Length - Supplies the length of the buffer in byte. This variable
  374. upon return recieves the remaining bytes free in the buffer
  375. Return Value:
  376. Status - Returns the status for the query
  377. --*/
  378. {
  379. ULONG LengthUsed;
  380. UNREFERENCED_PARAMETER( Vcb );
  381. PAGED_CODE();
  382. //
  383. // Check if the buffer we're given is long enough to contain "Raw"
  384. //
  385. LengthUsed = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]) + 6;
  386. if (*Length < LengthUsed) {
  387. return STATUS_BUFFER_OVERFLOW;
  388. }
  389. //
  390. // Set the output buffer
  391. //
  392. Buffer->FileSystemAttributes = 0;
  393. Buffer->MaximumComponentNameLength = 0;
  394. Buffer->FileSystemNameLength = 6;
  395. RtlCopyMemory( &Buffer->FileSystemName[0], L"RAW", 6 );
  396. //
  397. // Adjust the length variable
  398. //
  399. *Length -= LengthUsed;
  400. //
  401. // And return success to our caller
  402. //
  403. return STATUS_SUCCESS;
  404. }