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.

542 lines
16 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. FsCtrl.c
  5. Abstract:
  6. This module implements the File System Control routines for Rdbss. Fsctls on the device
  7. fcb are handled in another module.
  8. Author:
  9. Joe Linn [JoeLinn] 7-mar-95
  10. Revision History:
  11. Balan Sethu Raman 18-May-95 -- Integrated with mini rdrs
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include <dfsfsctl.h>
  16. // The local debug trace level
  17. #define Dbg (DEBUG_TRACE_FSCTRL)
  18. // Local procedure prototypes
  19. NTSTATUS
  20. RxUserFsCtrl ( RXCOMMON_SIGNATURE );
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, RxCommonFileSystemControl)
  23. #pragma alloc_text(PAGE, RxUserFsCtrl)
  24. #pragma alloc_text(PAGE, RxLowIoFsCtlShell)
  25. #pragma alloc_text(PAGE, RxLowIoFsCtlShellCompletion)
  26. #endif
  27. NTSTATUS
  28. RxCommonFileSystemControl ( RXCOMMON_SIGNATURE )
  29. /*++
  30. Routine Description:
  31. This is the common routine for doing FileSystem control operations called
  32. by both the fsd and fsp threads. What happens is that we pick off fsctls that we know about
  33. and remote the rest....remoting means sending them thru the lowio stuff which may/will pick off
  34. a few more. the ones that we pick off here (and currently return STATUS_NOT_IMPLEMENTED) and the
  35. ones for being an oplock provider and for doing volume mounts....we don't even have volume fcbs
  36. yet since this is primarily a localFS concept. nevertheless, these are not passed thru to the mini.
  37. Arguments:
  38. Return Value:
  39. RXSTATUS - The return status for the operation
  40. --*/
  41. {
  42. RxCaptureRequestPacket;
  43. RxCaptureParamBlock;
  44. RxCaptureFcb;
  45. RxCaptureFobx;
  46. RxCaptureFileObject;
  47. NTSTATUS Status;
  48. NODE_TYPE_CODE TypeOfOpen;
  49. BOOLEAN TryLowIo = TRUE;
  50. ULONG FsControlCode = capPARAMS->Parameters.FileSystemControl.FsControlCode;
  51. PAGED_CODE();
  52. RxDbgTrace(+1, Dbg, ("RxCommonFileSystemControl %08lx\n", RxContext));
  53. RxDbgTrace( 0, Dbg, ("Irp = %08lx\n", capReqPacket));
  54. RxDbgTrace( 0, Dbg, ("MinorFunction = %08lx\n", capPARAMS->MinorFunction));
  55. RxDbgTrace( 0, Dbg, ("FsControlCode = %08lx\n", FsControlCode));
  56. RxLog(("FsCtl %x %x %x %x",RxContext,capReqPacket,capPARAMS->MinorFunction,FsControlCode));
  57. ASSERT(capPARAMS->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL);
  58. switch (capPARAMS->MinorFunction) {
  59. case IRP_MN_USER_FS_REQUEST:
  60. {
  61. RxDbgTrace( 0, Dbg, ("FsControlCode = %08lx\n", FsControlCode));
  62. switch (FsControlCode) {
  63. case FSCTL_REQUEST_OPLOCK_LEVEL_1:
  64. case FSCTL_REQUEST_OPLOCK_LEVEL_2:
  65. case FSCTL_REQUEST_BATCH_OPLOCK:
  66. case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
  67. case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
  68. case FSCTL_OPLOCK_BREAK_NOTIFY:
  69. case FSCTL_OPLOCK_BREAK_ACK_NO_2:
  70. {
  71. // fsrtl oplock package is handled in common for all minirdrs
  72. //Status = RxOplockRequest( RXCOMMON_ARGUMENTS, &PostToFsp );
  73. Status = STATUS_NOT_IMPLEMENTED;
  74. TryLowIo = FALSE;
  75. }
  76. break;
  77. case FSCTL_LOCK_VOLUME:
  78. case FSCTL_UNLOCK_VOLUME:
  79. case FSCTL_DISMOUNT_VOLUME:
  80. case FSCTL_MARK_VOLUME_DIRTY:
  81. case FSCTL_IS_VOLUME_MOUNTED:
  82. {
  83. // Decode the file object, the only type of opens we accept are
  84. // user volume opens.
  85. TypeOfOpen = NodeType(capFcb);
  86. if (TypeOfOpen != RDBSS_NTC_VOLUME_FCB) {
  87. Status = STATUS_INVALID_PARAMETER;
  88. } else {
  89. //Status = RxFsdPostRequestWithResume(RxContext,RxCommonDevFCBFsCtl);
  90. Status = STATUS_NOT_IMPLEMENTED;
  91. }
  92. TryLowIo = FALSE;
  93. }
  94. break;
  95. case FSCTL_DFS_GET_REFERRALS:
  96. case FSCTL_DFS_REPORT_INCONSISTENCY:
  97. {
  98. if (!BooleanFlagOn(capFcb->pVNetRoot->pNetRoot->pSrvCall->Flags,SRVCALL_FLAG_DFS_AWARE_SERVER)) {
  99. TryLowIo = FALSE;
  100. Status = STATUS_DFS_UNAVAILABLE;
  101. }
  102. }
  103. break;
  104. default:
  105. break;
  106. }
  107. }
  108. break;
  109. default:
  110. break;
  111. }
  112. if (TryLowIo) {
  113. Status = RxLowIoFsCtlShell(RxContext);
  114. }
  115. if (RxContext->PostRequest) {
  116. Status = RxFsdPostRequest(RxContext);
  117. }
  118. RxDbgTrace(-1, Dbg, ("RxCommonFileSystemControl -> %08lx\n", Status));
  119. return Status;
  120. }
  121. ULONG RxEnablePeekBackoff = 1;
  122. NTSTATUS
  123. RxLowIoFsCtlShell( RXCOMMON_SIGNATURE )
  124. /*++
  125. Routine Description:
  126. This is the common routine for implementing the user's requests made
  127. through NtFsControlFile.
  128. Arguments:
  129. Irp - Supplies the Irp being processed
  130. Return Value:
  131. RXSTATUS - The return status for the operation
  132. --*/
  133. {
  134. RxCaptureFcb;
  135. RxCaptureRequestPacket;
  136. RxCaptureParamBlock;
  137. RxCaptureFobx;
  138. RxCaptureFileObject;
  139. NTSTATUS Status = STATUS_SUCCESS;
  140. BOOLEAN PostToFsp = FALSE;
  141. //BOOLEAN TryToRemoteIt = TRUE;
  142. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  143. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  144. ULONG FsControlCode = capPARAMS->Parameters.FileSystemControl.FsControlCode;
  145. BOOLEAN SubmitLowIoRequest = TRUE;
  146. PAGED_CODE();
  147. RxDbgTrace(+1, Dbg, ("RxLowIoFsCtlShell...\n", 0));
  148. RxDbgTrace( 0, Dbg, ("FsControlCode = %08lx\n", FsControlCode));
  149. RxInitializeLowIoContext(pLowIoContext,LOWIO_OP_FSCTL);
  150. switch (capPARAMS->MinorFunction) {
  151. case IRP_MN_USER_FS_REQUEST:
  152. {
  153. // The RDBSS filters out those FsCtls that can be handled without the intervention
  154. // of the mini rdr's. Currently all FsCtls are forwarded down to the mini rdr.
  155. switch (FsControlCode) {
  156. case FSCTL_PIPE_PEEK:
  157. {
  158. if (RxShouldRequestBeThrottled(&capFobx->Specific.NamedPipe.ThrottlingState)
  159. && RxEnablePeekBackoff) {
  160. PFILE_PIPE_PEEK_BUFFER pPeekBuffer;
  161. ASSERT(capReqPacket->UserBuffer != NULL);
  162. pPeekBuffer = (PFILE_PIPE_PEEK_BUFFER)capReqPacket->UserBuffer;
  163. SubmitLowIoRequest = FALSE;
  164. RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("RxLowIoFsCtlShell: Throttling Peek Request\n"));
  165. capReqPacket->IoStatus.Information = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER,Data);
  166. pPeekBuffer->ReadDataAvailable = 0;
  167. pPeekBuffer->NamedPipeState = FILE_PIPE_CONNECTED_STATE;
  168. pPeekBuffer->NumberOfMessages = MAXULONG;
  169. pPeekBuffer->MessageLength = 0;
  170. Status = STATUS_SUCCESS;
  171. RxContext->StoredStatus = Status;
  172. } else {
  173. RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("RxLowIoFsCtlShell: Throttling queries %ld\n",
  174. capFobx->Specific.NamedPipe.ThrottlingState.NumberOfQueries));
  175. RxLog(("ThrottlQs %lx %lx %lx %ld\n",
  176. RxContext,capFobx,&capFobx->Specific.NamedPipe.ThrottlingState,
  177. capFobx->Specific.NamedPipe.ThrottlingState.NumberOfQueries));
  178. }
  179. }
  180. break;
  181. default:
  182. break;
  183. } //end of the inner switch
  184. } //end of the case
  185. break;
  186. default:
  187. break;
  188. }
  189. if (SubmitLowIoRequest) {
  190. Status = RxLowIoSubmit(RxContext,RxLowIoFsCtlShellCompletion);
  191. }
  192. RxDbgTrace(-1, Dbg, ("RxLowIoFsCtlShell -> %08lx\n", Status ));
  193. return Status;
  194. }
  195. NTSTATUS
  196. RxLowIoFsCtlShellCompletion( RXCOMMON_SIGNATURE )
  197. /*++
  198. Routine Description:
  199. This is the completion routine for FSCTL requests passed down to the mini rdr
  200. Arguments:
  201. Irp - Supplies the Irp being processed
  202. Return Value:
  203. RXSTATUS - The return status for the operation
  204. --*/
  205. {
  206. RxCaptureRequestPacket;
  207. RxCaptureFcb;
  208. RxCaptureFobx;
  209. NTSTATUS Status;
  210. //NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  211. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  212. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  213. PAGED_CODE();
  214. Status = RxContext->StoredStatus;
  215. RxDbgTrace(+1, Dbg, ("RxLowIoFsCtlShellCompletion entry Status = %08lx\n", Status));
  216. switch (FsControlCode) {
  217. case FSCTL_PIPE_PEEK:
  218. {
  219. if ((Status == STATUS_SUCCESS) ||
  220. (Status == STATUS_BUFFER_OVERFLOW)) {
  221. // In the case of Peek operations a throttle mechanism is in place to
  222. // prevent the network from being flodded with requests which return 0
  223. // bytes.
  224. PFILE_PIPE_PEEK_BUFFER pPeekBuffer;
  225. pPeekBuffer = (PFILE_PIPE_PEEK_BUFFER)pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  226. if (pPeekBuffer->ReadDataAvailable == 0) {
  227. // The peek request returned zero bytes.
  228. RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("RxLowIoFsCtlShellCompletion: Enabling Throttling for Peek Request\n"));
  229. RxInitiateOrContinueThrottling(&capFobx->Specific.NamedPipe.ThrottlingState);
  230. RxLog(("ThrottlYes %lx %lx %lx %ld\n",
  231. RxContext,capFobx,&capFobx->Specific.NamedPipe.ThrottlingState,
  232. capFobx->Specific.NamedPipe.ThrottlingState.NumberOfQueries));
  233. } else {
  234. RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("RxLowIoFsCtlShellCompletion: Disabling Throttling for Peek Request\n"));
  235. RxTerminateThrottling(&capFobx->Specific.NamedPipe.ThrottlingState);
  236. RxLog(("ThrottlNo %lx %lx %lx %ld\n",
  237. RxContext,capFobx,&capFobx->Specific.NamedPipe.ThrottlingState,
  238. capFobx->Specific.NamedPipe.ThrottlingState.NumberOfQueries));
  239. }
  240. capReqPacket->IoStatus.Information = RxContext->InformationToReturn;
  241. }
  242. }
  243. break;
  244. default:
  245. if ((Status == STATUS_BUFFER_OVERFLOW) ||
  246. (Status == STATUS_SUCCESS)) {
  247. //ASSERT( RxContext->InformationToReturn == pLowIoContext->ParamsFor.FsCtl.OutputBufferLength);
  248. //capReqPacket->IoStatus.Information = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  249. capReqPacket->IoStatus.Information = RxContext->InformationToReturn;
  250. }
  251. break;
  252. }
  253. capReqPacket->IoStatus.Status = Status;
  254. RxDbgTrace(-1, Dbg, ("RxLowIoFsCtlShellCompletion exit Status = %08lx\n", Status));
  255. return Status;
  256. }
  257. //
  258. // Local support routine
  259. //
  260. //OPLOCKS we will want this eventually....don't take it out
  261. // there are embedded #ifs so it is not trivial to do this
  262. #if 0
  263. NTSTATUS
  264. RxOplockRequest (
  265. RXCOMMON_SIGNATURE,
  266. IN PBOOLEAN PostToFsp
  267. )
  268. /*++
  269. Routine Description:
  270. This is the common routine to handle oplock requests made via the
  271. NtFsControlFile call.
  272. Arguments:
  273. Irp - Supplies the Irp being processed
  274. Return Value:
  275. RXSTATUS - The return status for the operation
  276. --*/
  277. {
  278. NTSTATUS Status = STATUS_SUCCESS;
  279. RxCaptureRequestPacket;
  280. RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
  281. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  282. ULONG FsControlCode = capPARAMS->Parameters.FileSystemControl.FsControlCode;
  283. ULONG OplockCount;
  284. BOOLEAN AcquiredVcb = FALSE;
  285. PAGED_CODE();
  286. RxDbgTrace(+1, Dbg, ("RxOplockRequest...\n", 0));
  287. RxDbgTrace( 0, Dbg, ("FsControlCode = %08lx\n", FsControlCode));
  288. //
  289. // We only permit oplock requests on files.
  290. //
  291. if ( TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE ) {
  292. //RxCompleteRequest( RxContext, RxStatus(INVALID_PARAMETER) );
  293. RxDbgTrace(-1, Dbg, ("RxOplockRequest -> RxStatus(INVALID_PARAMETER\n)", 0));
  294. return STATUS_INVALID_PARAMETER;
  295. }
  296. //
  297. // Switch on the function control code. We grab the Fcb exclusively
  298. // for oplock requests, shared for oplock break acknowledgement.
  299. //
  300. switch ( FsControlCode ) {
  301. case FSCTL_REQUEST_OPLOCK_LEVEL_1:
  302. case FSCTL_REQUEST_OPLOCK_LEVEL_2:
  303. case FSCTL_REQUEST_BATCH_OPLOCK:
  304. //joejoe don't be an oplock filesystem yet
  305. RxCompleteContextAndReturn( STATUS_OPLOCK_NOT_GRANTED );
  306. //BUGBUG move this code down to wrapper.sav
  307. //BUGBUG should we return NOT_IMPLEMENTED instead???
  308. //i removed this code by #if so that we can see what we'll have to put in for oplocks
  309. #if 0
  310. if ( !RxAcquireSharedVcb( RxContext, capFcb->Vcb )) {
  311. //
  312. // If we can't acquire the Vcb, then this is an invalid
  313. // operation since we can't post Oplock requests.
  314. //
  315. RxDbgTrace(0, Dbg, ("Cannot acquire exclusive Vcb\n", 0));
  316. //RxCompleteRequest( RxContext, RxStatus(OPLOCK_NOT_GRANTED) );
  317. RxDbgTrace(-1, Dbg, ("RxOplockRequest -> RxStatus(OPLOCK_NOT_GRANTED\n)", 0));
  318. return STATUS_OPLOCK_NOT_GRANTED;
  319. }
  320. AcquiredVcb = TRUE;
  321. //
  322. // We set the wait parameter in the RxContext to FALSE. If this
  323. // request can't grab the Fcb and we are in the Fsp thread, then
  324. // we fail this request.
  325. //
  326. ClearFlag(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  327. if ( !RxAcquireExclusiveFcb( RxContext, capFcb )) {
  328. RxDbgTrace(0, Dbg, ("Cannot acquire exclusive Fcb\n", 0));
  329. RxReleaseVcb( RxContext, capFcb->Vcb );
  330. //
  331. // We fail this request.
  332. //
  333. Status = STATUS_OPLOCK_NOT_GRANTED;
  334. //RxCompleteRequest( RxContext, Status );
  335. RxDbgTrace(-1, Dbg, ("RxOplockRequest -> %08lx\n", Status ));
  336. return Status;
  337. }
  338. if (FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
  339. OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks( &capFcb->Specific.Fcb.FileLock );
  340. } else {
  341. OplockCount = capFcb->UncleanCount;
  342. }
  343. break;
  344. #endif
  345. case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
  346. case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
  347. case FSCTL_OPLOCK_BREAK_NOTIFY:
  348. case FSCTL_OPLOCK_BREAK_ACK_NO_2:
  349. //joejoe don't be an oplock filesystem yet
  350. RxCompleteContextAndReturn( STATUS_INVALID_OPLOCK_PROTOCOL );
  351. #if 0
  352. //just keep it for a model
  353. if ( !RxAcquireSharedFcb( RxContext, capFcb )) {
  354. RxDbgTrace(0, Dbg, ("Cannot acquire shared Fcb\n", 0));
  355. Status = RxFsdPostRequest( RxContext );
  356. RxDbgTrace(-1, Dbg, ("RxOplockRequest -> %08lx\n", Status ));
  357. return Status;
  358. }
  359. break;
  360. #endif
  361. default:
  362. RxBugCheck( FsControlCode, 0, 0 );
  363. }
  364. //
  365. // Use a try finally to free the Fcb.
  366. //
  367. try {
  368. ////
  369. //// Call the FsRtl routine to grant/acknowledge oplock.
  370. ////
  371. //
  372. //Status = FsRtlOplockFsctrl( &capFcb->Specific.Fcb.Oplock,
  373. // capReqPacket,
  374. // OplockCount );
  375. //
  376. // Set the flag indicating if Fast I/O is possible
  377. //
  378. capFcb->Header.IsFastIoPossible = RxIsFastIoPossible( capFcb );
  379. } finally {
  380. DebugUnwind( RxOplockRequest );
  381. //
  382. // Release all of our resources
  383. //
  384. if (AcquiredVcb) {
  385. RxReleaseVcb( RxContext, capFcb->Vcb );
  386. }
  387. RxReleaseFcb( RxContext, capFcb );
  388. if (!AbnormalTermination()) {
  389. //RxCompleteRequest_OLD( RxContext, RxNull, 0 );
  390. }
  391. RxDbgTrace(-1, Dbg, ("RxOplockRequest -> %08lx\n", Status ));
  392. }
  393. return Status;
  394. }
  395. #endif
  396.