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.

510 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. VolInfo.c
  5. Abstract:
  6. This module implements the volume information routines for Cdfs called by
  7. the dispatch driver.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Brian Andrew [BrianAn] 01-July-1995
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "CdProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO)
  19. //
  20. // Local support routines
  21. //
  22. NTSTATUS
  23. CdQueryFsVolumeInfo (
  24. IN PIRP_CONTEXT IrpContext,
  25. IN PVCB Vcb,
  26. IN PFILE_FS_VOLUME_INFORMATION Buffer,
  27. IN OUT PULONG Length
  28. );
  29. NTSTATUS
  30. CdQueryFsSizeInfo (
  31. IN PIRP_CONTEXT IrpContext,
  32. IN PVCB Vcb,
  33. IN PFILE_FS_SIZE_INFORMATION Buffer,
  34. IN OUT PULONG Length
  35. );
  36. NTSTATUS
  37. CdQueryFsDeviceInfo (
  38. IN PIRP_CONTEXT IrpContext,
  39. IN PVCB Vcb,
  40. IN PFILE_FS_DEVICE_INFORMATION Buffer,
  41. IN OUT PULONG Length
  42. );
  43. NTSTATUS
  44. CdQueryFsAttributeInfo (
  45. IN PIRP_CONTEXT IrpContext,
  46. IN PVCB Vcb,
  47. IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
  48. IN OUT PULONG Length
  49. );
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text(PAGE, CdCommonQueryVolInfo)
  52. #pragma alloc_text(PAGE, CdQueryFsAttributeInfo)
  53. #pragma alloc_text(PAGE, CdQueryFsDeviceInfo)
  54. #pragma alloc_text(PAGE, CdQueryFsSizeInfo)
  55. #pragma alloc_text(PAGE, CdQueryFsVolumeInfo)
  56. #endif
  57. NTSTATUS
  58. CdCommonQueryVolInfo (
  59. IN PIRP_CONTEXT IrpContext,
  60. IN PIRP Irp
  61. )
  62. /*++
  63. Routine Description:
  64. This is the common routine for querying volume information called by both
  65. the fsd and fsp threads.
  66. Arguments:
  67. Irp - Supplies the Irp being processed
  68. Return Value:
  69. NTSTATUS - The return status for the operation
  70. --*/
  71. {
  72. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  73. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  74. ULONG Length;
  75. TYPE_OF_OPEN TypeOfOpen;
  76. PFCB Fcb;
  77. PCCB Ccb;
  78. PAGED_CODE();
  79. //
  80. // Reference our input parameters to make things easier
  81. //
  82. Length = IrpSp->Parameters.QueryVolume.Length;
  83. //
  84. // Decode the file object and fail if this an unopened file object.
  85. //
  86. TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
  87. if (TypeOfOpen == UnopenedFileObject) {
  88. CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  89. return STATUS_INVALID_PARAMETER;
  90. }
  91. //
  92. // Acquire the Vcb for this volume.
  93. //
  94. CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
  95. //
  96. // Use a try-finally to facilitate cleanup.
  97. //
  98. try {
  99. //
  100. // Verify the Vcb.
  101. //
  102. CdVerifyVcb( IrpContext, Fcb->Vcb );
  103. //
  104. // Based on the information class we'll do different actions. Each
  105. // of the procedures that we're calling fills up the output buffer
  106. // if possible and returns true if it successfully filled the buffer
  107. // and false if it couldn't wait for any I/O to complete.
  108. //
  109. switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
  110. case FileFsSizeInformation:
  111. Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
  112. break;
  113. case FileFsVolumeInformation:
  114. Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
  115. break;
  116. case FileFsDeviceInformation:
  117. Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
  118. break;
  119. case FileFsAttributeInformation:
  120. Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
  121. break;
  122. }
  123. //
  124. // Set the information field to the number of bytes actually filled in
  125. //
  126. Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
  127. } finally {
  128. //
  129. // Release the Vcb.
  130. //
  131. CdReleaseVcb( IrpContext, Fcb->Vcb );
  132. }
  133. //
  134. // Complete the request if we didn't raise.
  135. //
  136. CdCompleteRequest( IrpContext, Irp, Status );
  137. return Status;
  138. }
  139. //
  140. // Local support routine
  141. //
  142. NTSTATUS
  143. CdQueryFsVolumeInfo (
  144. IN PIRP_CONTEXT IrpContext,
  145. IN PVCB Vcb,
  146. IN PFILE_FS_VOLUME_INFORMATION Buffer,
  147. IN OUT PULONG Length
  148. )
  149. /*++
  150. Routine Description:
  151. This routine implements the query volume info call
  152. Arguments:
  153. Vcb - Vcb for this volume.
  154. Buffer - Supplies a pointer to the output buffer where the information
  155. is to be returned
  156. Length - Supplies the length of the buffer in byte. This variable
  157. upon return recieves the remaining bytes free in the buffer
  158. Return Value:
  159. NTSTATUS - Returns the status for the query
  160. --*/
  161. {
  162. ULONG BytesToCopy;
  163. NTSTATUS Status = STATUS_SUCCESS;
  164. PAGED_CODE();
  165. //
  166. // Fill in the data from the Vcb.
  167. //
  168. Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
  169. Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
  170. Buffer->SupportsObjects = FALSE;
  171. *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
  172. //
  173. // Check if the buffer we're given is long enough
  174. //
  175. if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
  176. BytesToCopy = Vcb->Vpb->VolumeLabelLength;
  177. } else {
  178. BytesToCopy = *Length;
  179. Status = STATUS_BUFFER_OVERFLOW;
  180. }
  181. //
  182. // Copy over what we can of the volume label, and adjust *Length
  183. //
  184. Buffer->VolumeLabelLength = BytesToCopy;
  185. if (BytesToCopy) {
  186. RtlCopyMemory( &Buffer->VolumeLabel[0],
  187. &Vcb->Vpb->VolumeLabel[0],
  188. BytesToCopy );
  189. }
  190. *Length -= BytesToCopy;
  191. //
  192. // Set our status and return to our caller
  193. //
  194. return Status;
  195. }
  196. //
  197. // Local support routine
  198. //
  199. NTSTATUS
  200. CdQueryFsSizeInfo (
  201. IN PIRP_CONTEXT IrpContext,
  202. IN PVCB Vcb,
  203. IN PFILE_FS_SIZE_INFORMATION Buffer,
  204. IN OUT PULONG Length
  205. )
  206. /*++
  207. Routine Description:
  208. This routine implements the query volume size call.
  209. Arguments:
  210. Vcb - Vcb for this volume.
  211. Buffer - Supplies a pointer to the output buffer where the information
  212. is to be returned
  213. Length - Supplies the length of the buffer in byte. This variable
  214. upon return recieves the remaining bytes free in the buffer
  215. Return Value:
  216. NTSTATUS - Returns the status for the query
  217. --*/
  218. {
  219. PAGED_CODE();
  220. //
  221. // Fill in the output buffer.
  222. //
  223. Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
  224. Buffer->AvailableAllocationUnits.QuadPart = 0;
  225. Buffer->SectorsPerAllocationUnit = 1;
  226. Buffer->BytesPerSector = SECTOR_SIZE;
  227. //
  228. // Adjust the length variable
  229. //
  230. *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
  231. //
  232. // And return success to our caller
  233. //
  234. return STATUS_SUCCESS;
  235. }
  236. //
  237. // Local support routine
  238. //
  239. NTSTATUS
  240. CdQueryFsDeviceInfo (
  241. IN PIRP_CONTEXT IrpContext,
  242. IN PVCB Vcb,
  243. IN PFILE_FS_DEVICE_INFORMATION Buffer,
  244. IN OUT PULONG Length
  245. )
  246. /*++
  247. Routine Description:
  248. This routine implements the query volume device call.
  249. Arguments:
  250. Vcb - Vcb for this volume.
  251. Buffer - Supplies a pointer to the output buffer where the information
  252. is to be returned
  253. Length - Supplies the length of the buffer in byte. This variable
  254. upon return recieves the remaining bytes free in the buffer
  255. Return Value:
  256. NTSTATUS - Returns the status for the query
  257. --*/
  258. {
  259. PAGED_CODE();
  260. //
  261. // Update the output buffer.
  262. //
  263. Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
  264. Buffer->DeviceType = FILE_DEVICE_CD_ROM;
  265. //
  266. // Adjust the length variable
  267. //
  268. *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
  269. //
  270. // And return success to our caller
  271. //
  272. return STATUS_SUCCESS;
  273. }
  274. //
  275. // Local support routine
  276. //
  277. NTSTATUS
  278. CdQueryFsAttributeInfo (
  279. IN PIRP_CONTEXT IrpContext,
  280. IN PVCB Vcb,
  281. IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
  282. IN OUT PULONG Length
  283. )
  284. /*++
  285. Routine Description:
  286. This routine implements the query volume attribute call.
  287. Arguments:
  288. Vcb - Vcb for this volume.
  289. Buffer - Supplies a pointer to the output buffer where the information
  290. is to be returned
  291. Length - Supplies the length of the buffer in byte. This variable
  292. upon return recieves the remaining bytes free in the buffer
  293. Return Value:
  294. NTSTATUS - Returns the status for the query
  295. --*/
  296. {
  297. ULONG BytesToCopy;
  298. NTSTATUS Status = STATUS_SUCCESS;
  299. PAGED_CODE();
  300. //
  301. // Fill out the fixed portion of the buffer.
  302. //
  303. Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
  304. FILE_READ_ONLY_VOLUME;
  305. if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
  306. SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
  307. Buffer->MaximumComponentNameLength = 110;
  308. } else {
  309. Buffer->MaximumComponentNameLength = 221;
  310. }
  311. *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
  312. //
  313. // Make sure we can copy full unicode characters.
  314. //
  315. ClearFlag( *Length, 1 );
  316. //
  317. // Determine how much of the file system name will fit.
  318. //
  319. if (*Length >= 8) {
  320. BytesToCopy = 8;
  321. } else {
  322. BytesToCopy = *Length;
  323. Status = STATUS_BUFFER_OVERFLOW;
  324. }
  325. *Length -= BytesToCopy;
  326. //
  327. // Do the file system name.
  328. //
  329. Buffer->FileSystemNameLength = BytesToCopy;
  330. RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
  331. //
  332. // And return to our caller
  333. //
  334. return Status;
  335. }