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.

541 lines
15 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: VOLINFO.C
  4. //
  5. // Contents: This module implements the volume information routines for
  6. // Dfs called by the dispatch driver.
  7. //
  8. // Functions: DfsFsdQueryVolumeInformation
  9. // DfsFspQueryVolumeInformation
  10. // DfsCommonQueryVolumeInformation
  11. // DfsFsdSetVolumeInformation
  12. // DfsFspSetVolumeInformation
  13. // DfsCommonSetVolumeInformation
  14. //
  15. // Notes: The Query information call is a candidate for directly
  16. // passing through via DfsVolumePassThrough. We'll keep
  17. // the entry point around for now as a convenient place
  18. // for breakpointing and tracing volume information calls.
  19. //
  20. // History: 12 Nov 1991 AlanW Created from CDFS souce.
  21. //
  22. //-----------------------------------------------------------------------------
  23. #include "dfsprocs.h"
  24. #include "mupwml.h"
  25. //
  26. // The local debug trace level
  27. //
  28. #define Dbg (DEBUG_TRACE_VOLINFO)
  29. //
  30. // Local procedure prototypes
  31. //
  32. NTSTATUS
  33. DfsCommonQueryVolumeInformation (
  34. IN PIRP_CONTEXT IrpContext,
  35. IN PIRP Irp
  36. );
  37. NTSTATUS
  38. DfsCommonSetVolumeInformation (
  39. IN PIRP_CONTEXT IrpContext,
  40. IN PIRP Irp
  41. );
  42. #define DfsSetFsLabelInfo(irpc,pvcb,pbuf) (STATUS_ACCESS_DENIED)
  43. #ifdef ALLOC_PRAGMA
  44. #pragma alloc_text( PAGE, DfsFsdQueryVolumeInformation )
  45. #pragma alloc_text( PAGE, DfsFspQueryVolumeInformation )
  46. #pragma alloc_text( PAGE, DfsCommonQueryVolumeInformation )
  47. #pragma alloc_text( PAGE, DfsFsdSetVolumeInformation )
  48. #pragma alloc_text( PAGE, DfsFspSetVolumeInformation )
  49. #pragma alloc_text( PAGE, DfsCommonSetVolumeInformation )
  50. #endif // ALLOC_PRAGMA
  51. //+-------------------------------------------------------------------
  52. //
  53. // Function: DfsFsdQueryVolumeInformation, public
  54. //
  55. // Synopsis: This routine implements the Fsd part of the
  56. // NtQueryVolumeInformation API call.
  57. //
  58. // Arguments: [DeviceObject] -- Supplies the device object where the file
  59. // being queried exists.
  60. // [Irp] -- Supplies the Irp being processed.
  61. //
  62. // Returns: NTSTATUS - The FSD status for the Irp.
  63. //
  64. //--------------------------------------------------------------------
  65. NTSTATUS
  66. DfsFsdQueryVolumeInformation (
  67. IN PDEVICE_OBJECT DeviceObject,
  68. IN PIRP Irp
  69. ) {
  70. NTSTATUS Status;
  71. PIRP_CONTEXT IrpContext;
  72. DfsDbgTrace(+1, Dbg, "DfsFsdQueryVolumeInformation: Entered\n", 0);
  73. if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) {
  74. DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
  75. DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation - Mup file\n", 0);
  76. return( STATUS_INVALID_DEVICE_REQUEST );
  77. }
  78. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  79. Status = DfsVolumePassThrough(DeviceObject, Irp);
  80. DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation: Exit -> %08x\n",
  81. ULongToPtr(Status) );
  82. return Status;
  83. }
  84. //
  85. // Call the common query routine, with blocking allowed if synchronous
  86. //
  87. FsRtlEnterFileSystem();
  88. try {
  89. IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
  90. if (IrpContext == NULL)
  91. ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
  92. Status = DfsCommonQueryVolumeInformation( IrpContext, Irp );
  93. } except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
  94. //
  95. // We had some trouble trying to perform the requested
  96. // operation, so we'll abort the I/O request with
  97. // the error status that we get back from the
  98. // execption code
  99. //
  100. Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
  101. }
  102. FsRtlExitFileSystem();
  103. //
  104. // And return to our caller
  105. //
  106. DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation: Exit -> %08x\n",
  107. ULongToPtr(Status) );
  108. return Status;
  109. UNREFERENCED_PARAMETER( DeviceObject );
  110. }
  111. //+-------------------------------------------------------------------
  112. //
  113. // Function: DfsFspQueryVolumeInformation, public
  114. //
  115. // Synopsis: This routine implements the FSP part of the
  116. // NtQueryVolumeInformation API call.
  117. //
  118. // Arguments: [IrpContext] -- the IRP_CONTEXT for the request
  119. // [Irp] -- Supplies the Irp being processed.
  120. //
  121. // Returns: Nothing
  122. //
  123. //--------------------------------------------------------------------
  124. VOID
  125. DfsFspQueryVolumeInformation (
  126. IN PIRP_CONTEXT IrpContext,
  127. IN PIRP Irp
  128. )
  129. {
  130. DfsDbgTrace(+1, Dbg, "DfsFspQueryVolumeInformation: Entered\n", 0);
  131. //
  132. // Call the common query routine.
  133. //
  134. (VOID)DfsCommonQueryVolumeInformation( IrpContext, Irp );
  135. //
  136. // And return to our caller
  137. //
  138. DfsDbgTrace(-1, Dbg, "DfsFspQueryVolumeInformation: Exit -> VOID\n", 0);
  139. return;
  140. }
  141. //+-------------------------------------------------------------------
  142. //
  143. // Function: DfsCommonQueryVolumeInformation, private
  144. //
  145. // Synopsis: This is the common routine for querying volume information
  146. // called by both the FSD and FSP threads.
  147. //
  148. // Arguments: [IrpContext] -- Supplies the context block for the IRP
  149. // [Irp] -- Supplies the IRP being processed
  150. //
  151. // Returns: NTSTATUS - The return status for the operation
  152. //
  153. //--------------------------------------------------------------------
  154. NTSTATUS
  155. DfsCommonQueryVolumeInformation (
  156. IN PIRP_CONTEXT IrpContext,
  157. IN PIRP Irp
  158. ) {
  159. NTSTATUS Status;
  160. PIO_STACK_LOCATION IrpSp;
  161. PIO_STACK_LOCATION NextIrpSp;
  162. PFILE_OBJECT FileObject;
  163. PDFS_VCB Vcb;
  164. PDFS_FCB Fcb;
  165. ULONG Length;
  166. FS_INFORMATION_CLASS FsInformationClass;
  167. PVOID Buffer;
  168. TYPE_OF_OPEN TypeOfOpen;
  169. //
  170. // Get the current stack location
  171. //
  172. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  173. FileObject = IrpSp->FileObject;
  174. DfsDbgTrace(+1, Dbg, "DfsCommonQueryVolumeInformation: Entered\n", 0);
  175. DfsDbgTrace( 0, Dbg, "Irp = %08x\n", Irp );
  176. DfsDbgTrace( 0, Dbg, "->Length = %08x\n", ULongToPtr(IrpSp->Parameters.QueryVolume.Length) );
  177. DfsDbgTrace( 0, Dbg, "->FsInformationClass = %08x\n", IrpSp->Parameters.QueryVolume.FsInformationClass);
  178. DfsDbgTrace( 0, Dbg, "->Buffer = %08x\n", Irp->AssociatedIrp.SystemBuffer);
  179. //
  180. // Reference our input parameters to make things easier
  181. //
  182. Length = IrpSp->Parameters.QueryVolume.Length;
  183. FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
  184. Buffer = Irp->AssociatedIrp.SystemBuffer;
  185. //
  186. // Decode the file object to get the Vcb
  187. //
  188. TypeOfOpen = DfsDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb);
  189. try {
  190. Status = STATUS_INVALID_PARAMETER;
  191. //
  192. // Case on the type of open.
  193. //
  194. switch (TypeOfOpen) {
  195. default:
  196. DfsDbgTrace(0, Dbg,
  197. "DfsCommonQueryVolumeInfo: Unknown open type\n", 0);
  198. invalid:
  199. // NOTE: FALL THROUGH
  200. case FilesystemDeviceOpen:
  201. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
  202. Status = STATUS_INVALID_DEVICE_REQUEST;
  203. break;
  204. case LogicalRootDeviceOpen:
  205. DfsDbgTrace(0, Dbg,
  206. "DfsCommonQueryVolumeInfo: Logical root open\n", 0);
  207. goto invalid;
  208. case RedirectedFileOpen:
  209. //
  210. // Nothing special is done base on the information class.
  211. // We simply pass each request through to the underlying
  212. // file system and let it handle the request.
  213. //
  214. //
  215. // Copy the stack from one to the next...
  216. //
  217. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  218. (*NextIrpSp) = (*IrpSp);
  219. IoSetCompletionRoutine( Irp,
  220. NULL,
  221. NULL,
  222. FALSE,
  223. FALSE,
  224. FALSE);
  225. //
  226. // Call the next device in the chain
  227. //
  228. Status = IoCallDriver( Fcb->TargetDevice, Irp );
  229. MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonQueryVolumeInformation_Error_IoCallDriver,
  230. LOGSTATUS(Status)
  231. LOGPTR(Irp)
  232. LOGPTR(FileObject));
  233. //
  234. // The IRP will be completed by the called driver. We have
  235. // no need for the IrpContext in the completion routine.
  236. //
  237. DfsDeleteIrpContext(IrpContext);
  238. IrpContext = NULL;
  239. Irp = NULL;
  240. break;
  241. }
  242. } finally {
  243. DfsDbgTrace(-1, Dbg, "DfsCommonQueryVolumeInformation: Exit -> %08x\n",
  244. ULongToPtr(Status) );
  245. }
  246. return Status;
  247. }
  248. //+-------------------------------------------------------------------
  249. //
  250. // Function: DfsFsdSetVolumeInformation, public
  251. //
  252. // Synopsis: This routine implements the Fsd part of the
  253. // NtSetVolumeInformation API call.
  254. //
  255. // Arguments: [DeviceObject] -- Supplies the device object where the file
  256. // being queried exists.
  257. // [Irp] -- Supplies the Irp being processed.
  258. //
  259. // Returns: NTSTATUS - The FSD status for the Irp.
  260. //
  261. //--------------------------------------------------------------------
  262. NTSTATUS
  263. DfsFsdSetVolumeInformation (
  264. IN PDEVICE_OBJECT DeviceObject,
  265. IN PIRP Irp
  266. ) {
  267. NTSTATUS Status;
  268. PIRP_CONTEXT IrpContext;
  269. DfsDbgTrace(+1, Dbg, "DfsFsdSetVolumeInformation: Entered\n", 0);
  270. if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) {
  271. DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
  272. DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation - Mup file\n", 0);
  273. return( STATUS_INVALID_DEVICE_REQUEST );
  274. }
  275. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  276. Status = DfsVolumePassThrough(DeviceObject, Irp);
  277. DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation: Exit -> %08x\n",
  278. ULongToPtr(Status) );
  279. return Status;
  280. }
  281. //
  282. // Call the common Set routine, with blocking allowed if synchronous
  283. //
  284. FsRtlEnterFileSystem();
  285. try {
  286. IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
  287. if (IrpContext == NULL)
  288. ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
  289. Status = DfsCommonSetVolumeInformation( IrpContext, Irp );
  290. } except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
  291. //
  292. // We had some trouble trying to perform the requested
  293. // operation, so we'll abort the I/O request with
  294. // the error status that we get back from the
  295. // execption code
  296. //
  297. Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
  298. }
  299. FsRtlExitFileSystem();
  300. //
  301. // And return to our caller
  302. //
  303. DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation: Exit -> %08x\n",
  304. ULongToPtr(Status) );
  305. return Status;
  306. UNREFERENCED_PARAMETER( DeviceObject );
  307. }
  308. //+-------------------------------------------------------------------
  309. //
  310. // Function: DfsFspSetVolumeInformation, public
  311. //
  312. // Synopsis: This routine implements the FSP part of the
  313. // NtSetVolumeInformation API call.
  314. //
  315. // Arguments: [IrpContext] -- the IRP_CONTEXT for the request
  316. // [Irp] -- Supplies the Irp being processed.
  317. //
  318. // Returns: Nothing
  319. //
  320. //--------------------------------------------------------------------
  321. VOID
  322. DfsFspSetVolumeInformation (
  323. IN PIRP_CONTEXT IrpContext,
  324. IN PIRP Irp
  325. )
  326. {
  327. DfsDbgTrace(+1, Dbg, "DfsFspSetVolumeInformation: Entered\n", 0);
  328. //
  329. // Call the common Set routine.
  330. //
  331. (VOID)DfsCommonSetVolumeInformation( IrpContext, Irp );
  332. //
  333. // And return to our caller
  334. //
  335. DfsDbgTrace(-1, Dbg, "DfsFspSetVolumeInformation: Exit -> VOID\n", 0);
  336. return;
  337. }
  338. //+-------------------------------------------------------------------
  339. //
  340. // Function: DfsCommonSetVolumeInformation, private
  341. //
  342. // Synopsis: This is the common routine for Seting volume information
  343. // called by both the FSD and FSP threads.
  344. //
  345. // Arguments: [IrpContext] -- Supplies the context block for the IRP
  346. // [Irp] -- Supplies the IRP being processed
  347. //
  348. // Returns: NTSTATUS - The return status for the operation
  349. //
  350. //--------------------------------------------------------------------
  351. NTSTATUS
  352. DfsCommonSetVolumeInformation (
  353. IN PIRP_CONTEXT IrpContext,
  354. IN PIRP Irp
  355. ) {
  356. NTSTATUS Status;
  357. PIO_STACK_LOCATION IrpSp;
  358. PDFS_VCB Vcb;
  359. PDFS_FCB Fcb;
  360. FS_INFORMATION_CLASS FsInformationClass;
  361. PVOID Buffer;
  362. TYPE_OF_OPEN TypeOfOpen;
  363. //
  364. // Get the current stack location
  365. //
  366. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  367. DfsDbgTrace(+1, Dbg, "DfsCommonSetVolumeInformation: Entered\n", 0);
  368. DfsDbgTrace( 0, Dbg, "Irp = %08x\n", Irp );
  369. DfsDbgTrace( 0, Dbg, "->Length = %08x\n", ULongToPtr(IrpSp->Parameters.SetVolume.Length) );
  370. DfsDbgTrace( 0, Dbg, "->FsInformationClass = %08x\n", IrpSp->Parameters.SetVolume.FsInformationClass);
  371. DfsDbgTrace( 0, Dbg, "->Buffer = %08x\n", Irp->AssociatedIrp.SystemBuffer);
  372. //
  373. // Reference our input parameters to make things easier
  374. //
  375. FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
  376. Buffer = Irp->AssociatedIrp.SystemBuffer;
  377. //
  378. // Decode the file object to get the Vcb
  379. //
  380. TypeOfOpen = DfsDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb);
  381. try {
  382. Status = STATUS_INVALID_PARAMETER;
  383. //
  384. // Case on the type of open.
  385. //
  386. switch (TypeOfOpen) {
  387. default:
  388. DfsDbgTrace(0, Dbg, "DfsCommonSetVolumeInfo: Unknown open type\n", 0);
  389. // NOTE: FALL THROUGH
  390. case FilesystemDeviceOpen:
  391. Status = STATUS_INVALID_DEVICE_REQUEST;
  392. break;
  393. case LogicalRootDeviceOpen:
  394. case RedirectedFileOpen:
  395. //
  396. // Based on the information class we'll do different actions.
  397. // Each of the procedures that we're calling fills up the output
  398. // buffer if possible and returns true if it successfully filled
  399. // the buffer and false if it couldn't wait for any I/O to
  400. // complete.
  401. //
  402. switch (FsInformationClass) {
  403. case FileFsLabelInformation:
  404. Status = DfsSetFsLabelInfo( IrpContext, Vcb, Buffer);
  405. break;
  406. default:
  407. DfsDbgTrace(0, Dbg, "DfsCommonSetVolumeInfo: Unknown InformationClass\n", 0);
  408. Status = STATUS_INVALID_DEVICE_REQUEST;
  409. break;
  410. }
  411. }
  412. } finally {
  413. if (!AbnormalTermination()) {
  414. DfsCompleteRequest( IrpContext, Irp, Status );
  415. }
  416. DfsDbgTrace(-1, Dbg, "DfsCommonSetVolumeInformation: Exit -> %08x\n",
  417. ULongToPtr(Status) );
  418. }
  419. return Status;
  420. }