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.

521 lines
15 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. // DfsCommonSetInformation - Implement SetInformationFile for DFS
  12. // DfsSetRenameInfo - Takes care of rename restrictions.
  13. // DfsSetDispositionInfo - Enforces Deletion of StgId restrictions.
  14. //
  15. // Notes: No query information routines are presently used.
  16. // These requests are passed directly through to a redirected
  17. // file (if one exists).
  18. //
  19. // History: 30 Jun 1992 AlanW Created from FastFAT source.
  20. // 09 Feb 1994 SudK Added Rename/Delete restrictions.
  21. //
  22. //--------------------------------------------------------------------------
  23. #include "dfsprocs.h"
  24. #include "attach.h"
  25. #include "localvol.h"
  26. #include "dfswml.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 Irp,
  37. BOOLEAN DfsEnable
  38. );
  39. NTSTATUS
  40. DfsSetDispositionInfo (
  41. IN PIRP Irp
  42. );
  43. NTSTATUS
  44. DfsSetRenameInfo (
  45. IN PIRP Irp);
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text ( PAGE, DfsFsdSetInformation )
  48. #pragma alloc_text ( PAGE, DfsCommonSetInformation )
  49. #pragma alloc_text ( PAGE, DfsSetDispositionInfo )
  50. #pragma alloc_text ( PAGE, DfsSetRenameInfo )
  51. #endif // ALLOC_PRAGMA
  52. //+-------------------------------------------------------------------
  53. //
  54. // Function: DfsFsdSetInformation, public
  55. //
  56. // Synopsis: This routine implements the FSD part of the
  57. // NtSetInformationFile API call.
  58. //
  59. // Arguments: [DeviceObject] -- Supplies the volume device object where
  60. // the file being set exists.
  61. // [Irp] -- Supplies the Irp being processed.
  62. //
  63. // Returns: NTSTATUS - The FSD status for the Irp.
  64. //
  65. //--------------------------------------------------------------------
  66. NTSTATUS
  67. DfsFsdSetInformation (
  68. IN PDEVICE_OBJECT DeviceObject,
  69. IN PIRP Irp
  70. ) {
  71. NTSTATUS Status;
  72. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  73. PFILE_OBJECT FileObject = irpSp->FileObject;
  74. ASSERT(ARGUMENT_PRESENT(DeviceObject));
  75. ASSERT(ARGUMENT_PRESENT(Irp));
  76. DebugTrace(+1, Dbg, "DfsFsdSetInformation\n", 0);
  77. DFS_TRACE_LOW(TRACE_IRP, DfsFsdSetInformation_Entry,
  78. LOGPTR(FileObject)
  79. LOGPTR(Irp));
  80. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  81. //
  82. // For local paths, we need to protect exit points and
  83. // local storage IDs against rename and delete. Otherwise,
  84. // pass the request along to the local file system driver.
  85. //
  86. Status = DfsCommonSetInformation(
  87. Irp,
  88. ((PDFS_VOLUME_OBJECT)DeviceObject)->DfsEnable);
  89. } else {
  90. Status = DfsVolumePassThrough( DeviceObject, Irp );
  91. }
  92. DebugTrace(-1, Dbg, "DfsFsdSetInformation: Exit -> %08lx\n", ULongToPtr( Status ));
  93. DFS_TRACE_LOW(TRACE_IRP, DfsFsdSetInformation_Exit,
  94. LOGSTATUS(Status)
  95. LOGPTR(FileObject)
  96. LOGPTR(Irp));
  97. return( Status );
  98. }
  99. //+-------------------------------------------------------------------
  100. //
  101. // Function: DfsCommonSetInformation, private
  102. //
  103. // Synopsis: This is the common routine for setting file information called
  104. // by both the FSD and FSP threads.
  105. //
  106. // Arguments: [Irp] -- Supplies the Irp being processed
  107. //
  108. // Returns: NTSTATUS - The return status for the operation
  109. //
  110. //--------------------------------------------------------------------
  111. //
  112. NTSTATUS
  113. DfsCommonSetInformation (
  114. IN PIRP Irp,
  115. IN BOOLEAN DfsEnabled
  116. ) {
  117. NTSTATUS Status = STATUS_SUCCESS;
  118. PIO_STACK_LOCATION IrpSp;
  119. PIO_STACK_LOCATION NextIrpSp;
  120. PFILE_OBJECT FileObject;
  121. FILE_INFORMATION_CLASS FileInformationClass;
  122. PDEVICE_OBJECT Vdo, DeviceObject;
  123. //
  124. // Get the current stack location
  125. //
  126. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  127. DFS_TRACE_LOW(TRACE_IRP, DfsCommonSetInformation_Entry,
  128. LOGPTR(Irp)
  129. LOGPTR(IrpSp->FileObject)
  130. LOGBOOLEAN(DfsEnabled));
  131. DebugTrace(+1, Dbg, "DfsCommonSetInformation...\n", 0);
  132. DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  133. DebugTrace( 0, Dbg, "->Length = %08lx\n", ULongToPtr( IrpSp->Parameters.SetFile.Length ));
  134. DebugTrace( 0, Dbg, "->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass);
  135. DebugTrace( 0, Dbg, "->ReplaceFileObject = %08lx\n", IrpSp->Parameters.SetFile.FileObject);
  136. DebugTrace( 0, Dbg, "->ReplaceIfExists = %08lx\n", IrpSp->Parameters.SetFile.ReplaceIfExists);
  137. DebugTrace( 0, Dbg, "->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
  138. //
  139. // Reference our input parameters to make things easier
  140. //
  141. FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  142. FileObject = IrpSp->FileObject;
  143. DeviceObject = IrpSp->DeviceObject;
  144. try {
  145. //
  146. // Based on the information class we'll do different
  147. // actions. Each of the procedures that we're calling will either
  148. // complete the request of send the request off to the fsp
  149. // to do the work.
  150. //
  151. switch (FileInformationClass) {
  152. case FileRenameInformation:
  153. case FileDispositionInformation:
  154. if (DfsEnabled) {
  155. if (FileInformationClass == FileRenameInformation) {
  156. Status = DfsSetRenameInfo( Irp );
  157. }
  158. else {
  159. Status = DfsSetDispositionInfo( Irp );
  160. }
  161. if (Status != STATUS_MORE_PROCESSING_REQUIRED)
  162. break;
  163. }
  164. // NOTE: Fall through
  165. default:
  166. //
  167. // Copy the stack from one to the next...
  168. //
  169. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  170. (*NextIrpSp) = (*IrpSp);
  171. IoSetCompletionRoutine( Irp,
  172. NULL,
  173. NULL,
  174. FALSE,
  175. FALSE,
  176. FALSE);
  177. Vdo = ((PDFS_VOLUME_OBJECT)DeviceObject)->Provider.DeviceObject;
  178. Status = IoCallDriver( Vdo, Irp);
  179. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonDetInformation_Error_IoCallDriver,
  180. LOGPTR(Irp)
  181. LOGPTR(FileObject)
  182. LOGSTATUS(Status));
  183. //
  184. // The IRP will be completed by the called driver.
  185. //
  186. Irp = NULL;
  187. break;
  188. }
  189. } finally {
  190. if (!AbnormalTermination()) {
  191. DfsCompleteRequest( Irp, Status );
  192. }
  193. DebugTrace(-1, Dbg, "DfsCommonSetInformation -> %08lx\n", ULongToPtr( Status ));
  194. }
  195. DFS_TRACE_LOW(TRACE_IRP, DfsCommonSetInformation_Exit,
  196. LOGSTATUS(Status)
  197. LOGPTR(FileObject)
  198. LOGPTR(Irp));
  199. return Status;
  200. }
  201. //+-------------------------------------------------------------------
  202. //
  203. // Function: DfsSetDispositionInfo, private
  204. //
  205. // Synopsis: This routine performs the set name information for DFS. In
  206. // many cases, this is simply done by sending it along to the
  207. // redirected or attached file object. If, however, this is a
  208. // local volume and the storageId is about to be deleted the
  209. // the operation will be refused.
  210. //
  211. // Arguments: [Irp] -- Supplies the IRP being processed
  212. //
  213. // Returns: NTSTATUS - The result of this operation if it completes
  214. // without an exception. STATUS_MORE_PROCESSING_REQUIRED
  215. // is returned if the request should just be passed on
  216. // to the attached-to device.
  217. //
  218. //--------------------------------------------------------------------
  219. NTSTATUS
  220. DfsSetDispositionInfo (
  221. IN PIRP Irp
  222. )
  223. {
  224. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  225. PIO_STACK_LOCATION IrpSp;
  226. PFILE_OBJECT FileObject;
  227. PDEVICE_OBJECT DeviceObject;
  228. PDFS_PKT Pkt;
  229. PDFS_LOCAL_VOL_ENTRY lv;
  230. //
  231. // The following variables are for abnormal termination
  232. //
  233. BOOLEAN LockedPkt = FALSE;
  234. //
  235. // Get the current stack location
  236. //
  237. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  238. DeviceObject = IrpSp->DeviceObject;
  239. FileObject = IrpSp->FileObject;
  240. DebugTrace(+1, Dbg, "DfsSetDispositionInfo...\n", 0);
  241. try {
  242. PDFS_FCB fcb;
  243. fcb = DfsLookupFcb( FileObject );
  244. if (fcb != NULL) {
  245. DebugTrace(0, Dbg, "File Delete on %wZ attempted\n",
  246. &fcb->FullFileName);
  247. //
  248. // Now we have the full file name of file we are trying to delete
  249. //
  250. Pkt = _GetPkt();
  251. PktAcquireShared(Pkt, TRUE);
  252. LockedPkt = TRUE;
  253. if (DfsFileOnExitPath( Pkt, &fcb->FullFileName )) {
  254. try_return( Status = STATUS_ACCESS_DENIED );
  255. }
  256. }
  257. Status = STATUS_MORE_PROCESSING_REQUIRED;
  258. try_exit: NOTHING;
  259. } finally {
  260. //
  261. // Release the PKT if locked. FreeMemory if allocated.
  262. //
  263. if (LockedPkt)
  264. PktRelease(&DfsData.Pkt);
  265. DebugTrace(-1, Dbg, "DfsSetDispositionInfo -> %08lx\n", ULongToPtr( Status ));
  266. }
  267. return(Status);
  268. }
  269. NTSTATUS
  270. DfspRenameAllowed()
  271. {
  272. return( STATUS_SUCCESS );
  273. }
  274. //+--------------------------------------------------------------------------
  275. //
  276. // Function: DfsSetRenameInfo, private
  277. //
  278. // Synopsis: This routine performs the set name information for DFS. In
  279. // many cases, this is simply done by sending it along to the
  280. // redirected or attached file object. If, however, this is a
  281. // local volume and there are volume exit points below a
  282. // directory being renamed, DFS knowledge is being changed, and
  283. // the operation will be refused unless this is being done as
  284. // part of the rename DFS path administrative operation.
  285. //
  286. // Arguments: [Irp] -- Supplies the IRP being processed
  287. //
  288. // Returns: [STATUS_MORE_PROCESSING_REQUIRED] -- Caller should continue
  289. // processing of the Irp by forwarding it to the
  290. // underlying file system driver.
  291. //
  292. // [STATUS_NOT_SAME_DEVICE] -- Indicates the source file object
  293. // and the target file object are not on the same device.
  294. //
  295. // [STATUS_INVALID_PARAMETER] -- Operation is invalid for the
  296. // type of file object or target file object.
  297. //
  298. // [STATUS_INSUFFICIENT_RESOURCES] -- Unable to allocate memory
  299. // for the operation.
  300. //
  301. //---------------------------------------------------------------------------
  302. NTSTATUS
  303. DfsSetRenameInfo (
  304. IN PIRP Irp)
  305. {
  306. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  307. PIO_STACK_LOCATION IrpSp;
  308. PDEVICE_OBJECT DeviceObject;
  309. PDFS_VOLUME_OBJECT dfsVdo;
  310. PFILE_OBJECT FileObject;
  311. PFILE_OBJECT TargetFileObject;
  312. PDFS_PKT Pkt;
  313. PUNICODE_PREFIX_TABLE_ENTRY lvpfx;
  314. PDFS_LOCAL_VOL_ENTRY lv;
  315. PDFS_FCB fcb;
  316. //
  317. // The following variables are for abnormal termination
  318. //
  319. BOOLEAN LockedPkt = FALSE;
  320. //
  321. // Get the current stack location
  322. //
  323. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  324. DeviceObject = IrpSp->DeviceObject;
  325. dfsVdo = (PDFS_VOLUME_OBJECT) DeviceObject;
  326. TargetFileObject = IrpSp->Parameters.SetFile.FileObject;
  327. FileObject = IrpSp->FileObject;
  328. DebugTrace(+1, Dbg, "DfsSetRenameInfo...\n", 0);
  329. try {
  330. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  331. //
  332. // This is the hard case. We have to do a lookup of the local
  333. // name and look for conflicts.
  334. //
  335. fcb = DfsLookupFcb(FileObject);
  336. if (fcb != NULL) {
  337. DebugTrace(0, Dbg,
  338. "File Rename on %wZ attempted\n", &fcb->FullFileName);
  339. //
  340. // Now we have the full file name of file we are trying to rename.
  341. //
  342. Pkt = _GetPkt();
  343. PktAcquireShared(Pkt, TRUE);
  344. LockedPkt = TRUE;
  345. //
  346. // First we make sure that we are not renaming any storageId.
  347. //
  348. lvpfx = DfsNextUnicodePrefix(&Pkt->LocalVolTable, TRUE);
  349. while (lvpfx != NULL) {
  350. lv = CONTAINING_RECORD(
  351. lvpfx,
  352. DFS_LOCAL_VOL_ENTRY,
  353. PrefixTableEntry);
  354. if (DfsRtlPrefixPath(&fcb->FullFileName, &lv->LocalPath, TRUE)) {
  355. try_return(Status = STATUS_ACCESS_DENIED);
  356. }
  357. lvpfx = DfsNextUnicodePrefix(&Pkt->LocalVolTable, FALSE);
  358. }
  359. //
  360. // Now we only need to make sure that we are not renaming an
  361. // exit path.
  362. //
  363. if (DfsFileOnExitPath(Pkt, &fcb->FullFileName)) {
  364. //
  365. // If this is a namespace reorg then if caller is DfsManager
  366. // allow the access else fail the call.
  367. //
  368. if (DfspRenameAllowed()) {
  369. try_return(Status = STATUS_MORE_PROCESSING_REQUIRED);
  370. } else {
  371. try_return(Status = STATUS_ACCESS_DENIED);
  372. }
  373. }
  374. }
  375. } else {
  376. try_return(Status = STATUS_INVALID_DEVICE_REQUEST);
  377. }
  378. try_exit: NOTHING;
  379. } finally {
  380. //
  381. // Release the PKT if locked. FreeMemory if allocated.
  382. //
  383. if (LockedPkt)
  384. PktRelease(&DfsData.Pkt);
  385. }
  386. DebugTrace(-1, Dbg, "DfsSetRenameInfo -> %08lx\n", ULongToPtr( Status ));
  387. return(Status);
  388. }