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.

488 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: FILEINFO.C
  6. //
  7. // Contents: This module implements the File Information routines for
  8. // Dfs called by the dispatch driver.
  9. //
  10. // Functions: DfsFsdSetInformation - FSD entry point for NtSetInformationFile
  11. // DfsFspSetInformation - FSP entry point for NtSetInformationFile
  12. // DfsCommonSetInformation - Implement SetInformationFile for DFS
  13. // DfsSetRenameInfo - Takes care of rename restrictions.
  14. // DfsSetDispositionInfo - Enforces Deletion of StgId restrictions.
  15. //
  16. // Notes: No query information routines are presently used.
  17. // These requests are passed directly through to a redirected
  18. // file (if one exists).
  19. //
  20. // History: 30 Jun 1992 AlanW Created from FastFAT source.
  21. // 09 Feb 1994 SudK Added Rename/Delete restrictions.
  22. //
  23. //--------------------------------------------------------------------------
  24. #include "dfsprocs.h"
  25. #include "dnr.h"
  26. #include "mupwml.h"
  27. //
  28. // The local debug trace level
  29. //
  30. #define Dbg (DEBUG_TRACE_FILEINFO)
  31. //
  32. // Local procedure prototypes
  33. //
  34. NTSTATUS
  35. DfsCommonSetInformation (
  36. IN PIRP_CONTEXT IrpContext,
  37. IN PIRP Irp
  38. );
  39. NTSTATUS
  40. DfsSetDispositionInfo (
  41. IN PIRP Irp
  42. );
  43. NTSTATUS
  44. DfsSetRenameInfo (
  45. IN PIRP Irp,
  46. IN PDFS_VCB Vcb,
  47. IN PDFS_FCB Fcb
  48. );
  49. #ifdef ALLOC_PRAGMA
  50. #pragma alloc_text ( PAGE, DfsFsdQueryInformation )
  51. #pragma alloc_text ( PAGE, DfsFsdSetInformation )
  52. #pragma alloc_text ( PAGE, DfsFspSetInformation )
  53. #pragma alloc_text ( PAGE, DfsCommonSetInformation )
  54. #pragma alloc_text ( PAGE, DfsSetDispositionInfo )
  55. #pragma alloc_text ( PAGE, DfsSetRenameInfo )
  56. #endif // ALLOC_PRAGMA
  57. //+----------------------------------------------------------------------------
  58. //
  59. // Function: DfsFsdQueryInformation, public
  60. //
  61. // Synopsis: This routine implements the FSD part of the
  62. // NtQueryInformationFile API call
  63. //
  64. // Arguments: [DeviceObject] -- Supplies the volume device object where
  65. // the file being queried exists.
  66. // [Irp] -- Supplies the Irp being processed
  67. //
  68. // Returns: NTSTATUS - The FSD status for the Irp.
  69. //
  70. //-----------------------------------------------------------------------------
  71. NTSTATUS
  72. DfsFsdQueryInformation (
  73. IN PDEVICE_OBJECT DeviceObject,
  74. IN PIRP Irp)
  75. {
  76. NTSTATUS Status = STATUS_SUCCESS;
  77. PIO_STACK_LOCATION IrpSp;
  78. FILE_INFORMATION_CLASS FileInformationClass;
  79. PFILE_NAME_INFORMATION FileNameInfo;
  80. UNICODE_STRING FileNameToUse;
  81. ULONG BufferLength, BytesToCopy;
  82. PFILE_OBJECT FileObject;
  83. TYPE_OF_OPEN TypeOfOpen;
  84. PDFS_VCB Vcb;
  85. PDFS_FCB Fcb;
  86. BOOLEAN completeIrp;
  87. ASSERT(ARGUMENT_PRESENT(DeviceObject));
  88. ASSERT(ARGUMENT_PRESENT(Irp));
  89. DfsDbgTrace(+1, Dbg, "DfsFsdQueryInformation - Entered\n", 0);
  90. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  91. FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
  92. DfsDbgTrace(0, Dbg, "InfoLevel = %d\n", FileInformationClass);
  93. if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER ||
  94. DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM) {
  95. DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
  96. DfsDbgTrace(-1, Dbg, "DfsFsdQueryInformation - Mup/File System\n", 0);
  97. return( STATUS_INVALID_DEVICE_REQUEST );
  98. }
  99. ASSERT( DeviceObject->DeviceType == FILE_DEVICE_DFS );
  100. if (FileInformationClass != FileNameInformation &&
  101. FileInformationClass != FileAlternateNameInformation) {
  102. Status = DfsVolumePassThrough(DeviceObject, Irp);
  103. DfsDbgTrace(-1, Dbg,
  104. "DfsFsdQueryInformation: Exit -> %08lx\n", ULongToPtr(Status) );
  105. return Status;
  106. }
  107. FileObject = IrpSp->FileObject;
  108. //
  109. // Decode the file object. Remember that there need not be an Fcb always.
  110. //
  111. TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
  112. if (Fcb != NULL) {
  113. completeIrp = TRUE;
  114. switch (TypeOfOpen) {
  115. default:
  116. //
  117. // We cannot get info on a device open
  118. //
  119. Status = STATUS_INVALID_PARAMETER;
  120. break;
  121. case RedirectedFileOpen:
  122. case UnknownOpen:
  123. FileNameInfo = (PFILE_NAME_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
  124. BufferLength = IrpSp->Parameters.QueryFile.Length;
  125. if (FileInformationClass == FileAlternateNameInformation)
  126. FileNameToUse = Fcb->AlternateFileName;
  127. else
  128. FileNameToUse = Fcb->FullFileName;
  129. if (BufferLength < sizeof(FILE_NAME_INFORMATION)) {
  130. Status = STATUS_INVALID_PARAMETER;
  131. }
  132. if (FileNameToUse.Length == 0) {
  133. ASSERT(FileInformationClass == FileAlternateNameInformation);
  134. Status = DfsVolumePassThrough(DeviceObject, Irp);
  135. completeIrp = FALSE;
  136. } else {
  137. BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
  138. if (BufferLength < FileNameToUse.Length) {
  139. BytesToCopy = BufferLength;
  140. Status = STATUS_BUFFER_OVERFLOW;
  141. BufferLength = 0;
  142. }
  143. else {
  144. BytesToCopy = FileNameToUse.Length;
  145. BufferLength -= BytesToCopy;
  146. }
  147. FileNameInfo->FileNameLength = FileNameToUse.Length;
  148. if (BytesToCopy > 0) {
  149. RtlCopyMemory(
  150. (PVOID) &FileNameInfo->FileName,
  151. (PVOID) FileNameToUse.Buffer,
  152. BytesToCopy);
  153. }
  154. Irp->IoStatus.Information =
  155. IrpSp->Parameters.QueryFile.Length - BufferLength;
  156. }
  157. break;
  158. }
  159. if (completeIrp)
  160. DfsCompleteRequest( NULL, Irp, Status );
  161. } else {
  162. Status = STATUS_INVALID_PARAMETER;
  163. DfsCompleteRequest( NULL, Irp, Status );
  164. }
  165. //
  166. // And return to our caller
  167. //
  168. DfsDbgTrace(-1, Dbg, "DfsFsdQueryInformation -> %08lx\n", ULongToPtr(Status) );
  169. return Status;
  170. }
  171. //+-------------------------------------------------------------------
  172. //
  173. // Function: DfsFsdSetInformation, public
  174. //
  175. // Synopsis: This routine implements the FSD part of the
  176. // NtSetInformationFile API call.
  177. //
  178. // Arguments: [DeviceObject] -- Supplies the volume device object where
  179. // the file being set exists.
  180. // [Irp] -- Supplies the Irp being processed.
  181. //
  182. // Returns: NTSTATUS - The FSD status for the Irp.
  183. //
  184. //--------------------------------------------------------------------
  185. NTSTATUS
  186. DfsFsdSetInformation (
  187. IN PDEVICE_OBJECT DeviceObject,
  188. IN PIRP Irp
  189. ) {
  190. NTSTATUS Status;
  191. PIRP_CONTEXT IrpContext = NULL;
  192. ASSERT(ARGUMENT_PRESENT(DeviceObject));
  193. ASSERT(ARGUMENT_PRESENT(Irp));
  194. DfsDbgTrace(+1, Dbg, "DfsFsdSetInformation\n", 0);
  195. //
  196. // Call the common set routine, with blocking allowed if synchronous
  197. //
  198. FsRtlEnterFileSystem();
  199. try {
  200. IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
  201. if (IrpContext == NULL)
  202. ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
  203. Status = DfsCommonSetInformation( IrpContext, Irp );
  204. } except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
  205. //
  206. // We had some trouble trying to perform the requested
  207. // operation, so we'll abort the I/O request with
  208. // the error status that we get back from the
  209. // execption code
  210. //
  211. Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
  212. }
  213. FsRtlExitFileSystem();
  214. //
  215. // And return to our caller
  216. //
  217. DfsDbgTrace(-1, Dbg, "DfsFsdSetInformation -> %08lx\n", ULongToPtr(Status) );
  218. UNREFERENCED_PARAMETER( DeviceObject );
  219. return Status;
  220. }
  221. //+-------------------------------------------------------------------
  222. //
  223. // Function: DfsFspSetInformation, public
  224. //
  225. // Synopsis: This routine implements the FSP part of the
  226. // NtSetInformationFile API call.
  227. //
  228. // Arguments: [IrpContext] -- The IRP_CONTEXT record for the operation
  229. // [Irp] -- Supplies the Irp being processed.
  230. //
  231. // Returns: Nothing
  232. //
  233. //--------------------------------------------------------------------
  234. VOID
  235. DfsFspSetInformation (
  236. IN PIRP_CONTEXT IrpContext,
  237. IN PIRP Irp
  238. ) {
  239. DfsDbgTrace(+1, Dbg, "DfsFspSetInformation\n", 0);
  240. //
  241. // Call the common set routine. The Fsp is always allowed to block
  242. //
  243. (VOID)DfsCommonSetInformation( IrpContext, Irp );
  244. //
  245. // And return to our caller
  246. //
  247. DfsDbgTrace(-1, Dbg, "DfsFspSetInformation -> VOID\n", 0);
  248. return;
  249. }
  250. //+-------------------------------------------------------------------
  251. //
  252. // Function: DfsCommonSetInformation, private
  253. //
  254. // Synopsis: This is the common routine for setting file information called
  255. // by both the FSD and FSP threads.
  256. //
  257. // Arguments: [Irp] -- Supplies the Irp being processed
  258. //
  259. // Returns: NTSTATUS - The return status for the operation
  260. //
  261. //--------------------------------------------------------------------
  262. //
  263. NTSTATUS
  264. DfsCommonSetInformation (
  265. IN PIRP_CONTEXT IrpContext,
  266. IN PIRP Irp
  267. ) {
  268. NTSTATUS Status = STATUS_SUCCESS;
  269. PIO_STACK_LOCATION IrpSp;
  270. PIO_STACK_LOCATION NextIrpSp;
  271. PFILE_OBJECT FileObject;
  272. FILE_INFORMATION_CLASS FileInformationClass;
  273. PDEVICE_OBJECT Vdo, DeviceObject;
  274. TYPE_OF_OPEN TypeOfOpen;
  275. PDFS_VCB Vcb;
  276. PDFS_FCB Fcb;
  277. //
  278. // Get the current stack location
  279. //
  280. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  281. DfsDbgTrace(+1, Dbg, "DfsCommonSetInformation...\n", 0);
  282. DfsDbgTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  283. DfsDbgTrace( 0, Dbg, "->Length = %08lx\n", ULongToPtr(IrpSp->Parameters.SetFile.Length) );
  284. DfsDbgTrace( 0, Dbg, "->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass);
  285. DfsDbgTrace( 0, Dbg, "->ReplaceFileObject = %08lx\n", IrpSp->Parameters.SetFile.FileObject);
  286. DfsDbgTrace( 0, Dbg, "->ReplaceIfExists = %08lx\n", IrpSp->Parameters.SetFile.ReplaceIfExists);
  287. DfsDbgTrace( 0, Dbg, "->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
  288. //
  289. // Reference our input parameters to make things easier
  290. //
  291. FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  292. FileObject = IrpSp->FileObject;
  293. DeviceObject = IrpSp->DeviceObject;
  294. if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) {
  295. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
  296. DfsDbgTrace(-1, Dbg, "DfsCommonSetInformation - Mup file\n", 0);
  297. return( STATUS_INVALID_DEVICE_REQUEST );
  298. }
  299. //
  300. // Decode the file object. Remember that there need not be an Fcb always.
  301. //
  302. TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
  303. //
  304. // Set this handle as having modified the file
  305. //
  306. FileObject->Flags |= FO_FILE_MODIFIED;
  307. try {
  308. //
  309. // Case on the type of open we're dealing with
  310. //
  311. switch (TypeOfOpen) {
  312. default:
  313. //
  314. // We cannot set info on a device open
  315. //
  316. try_return( Status = STATUS_INVALID_PARAMETER );
  317. case RedirectedFileOpen:
  318. case UnknownOpen:
  319. break;
  320. }
  321. if (Fcb == NULL)
  322. try_return( Status = STATUS_INVALID_PARAMETER );
  323. //
  324. // Copy the stack from one to the next...
  325. //
  326. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  327. (*NextIrpSp) = (*IrpSp);
  328. IoSetCompletionRoutine( Irp,
  329. NULL,
  330. NULL,
  331. FALSE,
  332. FALSE,
  333. FALSE);
  334. //
  335. // Call the next device in the chain.
  336. //
  337. Status = IoCallDriver( Fcb->TargetDevice, Irp );
  338. MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonSetInformation_Error_IoCallDriver,
  339. LOGSTATUS(Status)
  340. LOGPTR(Irp)
  341. LOGPTR(FileObject));
  342. //
  343. // The IRP will be completed by the called driver. We have
  344. // no need for the IrpContext in the completion routine.
  345. //
  346. DfsDeleteIrpContext(IrpContext);
  347. IrpContext = NULL;
  348. Irp = NULL;
  349. try_exit: NOTHING;
  350. } finally {
  351. DebugUnwind( DfsCommonSetInformation );
  352. if (!AbnormalTermination()) {
  353. DfsCompleteRequest( IrpContext, Irp, Status );
  354. }
  355. DfsDbgTrace(-1, Dbg, "DfsCommonSetInformation -> %08lx\n", ULongToPtr(Status) );
  356. }
  357. return Status;
  358. }