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.

593 lines
18 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to
  7. file system control(FSCTL) and Io Device Control (IOCTL) operations on file system objects.
  8. Author:
  9. Balan Sethu Raman [SethuR] 7-March-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <dfsfsctl.h>
  15. //
  16. // The local debug trace level
  17. //
  18. RXDT_DefineCategory(FSCTRL);
  19. #define Dbg (DEBUG_TRACE_FSCTRL)
  20. NTSTATUS
  21. MRxProxyFsCtl(
  22. IN OUT PRX_CONTEXT RxContext)
  23. /*++
  24. Routine Description:
  25. This routine performs an FSCTL operation (remote) on a file across the network
  26. Arguments:
  27. RxContext - the RDBSS context
  28. Return Value:
  29. RXSTATUS - The return status for the operation
  30. Notes:
  31. The FSCTL's handled by a mini rdr can be classified into one of two categories. In the
  32. first category are those FSCTL's whose implementation are shared between RDBSS and the
  33. mini rdr's and in the second category are those FSCTL's which are totally implemented
  34. by the mini rdr's. To this a third category can be added, i.e., those FSCTL's which
  35. should never be seen by the mini rdr's. The third category is solely intended as a
  36. debugging aid.
  37. The FSCTL's handled by a mini rdr can be classified based on functionality
  38. --*/
  39. {
  40. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  41. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  42. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  43. RxDbgTrace(+1, Dbg, ("MRxProxyFsCtl...\n", 0));
  44. RxDbgTrace( 0, Dbg, ("MRxProxyFsCtl = %08lx\n", FsControlCode));
  45. switch (pLowIoContext->ParamsFor.FsCtl.MinorFunction) {
  46. case IRP_MN_USER_FS_REQUEST:
  47. switch (FsControlCode) {
  48. case FSCTL_PIPE_ASSIGN_EVENT :
  49. case FSCTL_PIPE_DISCONNECT :
  50. case FSCTL_PIPE_LISTEN :
  51. case FSCTL_PIPE_PEEK :
  52. case FSCTL_PIPE_QUERY_EVENT :
  53. case FSCTL_PIPE_TRANSCEIVE :
  54. case FSCTL_PIPE_WAIT :
  55. case FSCTL_PIPE_IMPERSONATE :
  56. case FSCTL_PIPE_SET_CLIENT_PROCESS :
  57. case FSCTL_PIPE_QUERY_CLIENT_PROCESS :
  58. case FSCTL_MAILSLOT_PEEK :
  59. case FSCTL_DFS_GET_REFERRALS:
  60. case FSCTL_DFS_REPORT_INCONSISTENCY:
  61. case FSCTL_LMR_TRANSACT :
  62. default:
  63. // Status = MRxProxyFsControl(RxContext);
  64. // Temporarily stubbed out till the buffer passing strategy has been
  65. // finalized.
  66. Status = STATUS_NOT_IMPLEMENTED;
  67. break;
  68. }
  69. break;
  70. default :
  71. break;
  72. }
  73. RxDbgTrace(-1, Dbg, ("MRxProxyFsCtl -> %08lx\n", Status ));
  74. return Status;
  75. }
  76. typedef struct _PROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT_ {
  77. PRX_CONTEXT pRxContext;
  78. //REQ_NOTIFY_CHANGE NotifyRequest;
  79. //PROXY_TRANSACTION_OPTIONS Options;
  80. //PROXY_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  81. } PROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT, *PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT;
  82. VOID
  83. MRxProxyNotifyChangeDirectoryCompletion(
  84. PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext)
  85. /*++
  86. Routine Description:
  87. This routine is invokde when a directory change notification operation is completed
  88. Arguments:
  89. RxContext - the RDBSS context
  90. Return Value:
  91. RXSTATUS - The return status for the operation
  92. Notes:
  93. This routine will always be called. This is true even if the change directory
  94. notification is cancelled. In such cases the memory allocated is freed without
  95. any inteaction with the wrapped. In cases os successful directory change
  96. notification completion the appropriate completion routine is invoked and the
  97. RxContext modified to prevent any cancellation from proceeding further.
  98. --*/
  99. {
  100. NTSTATUS Status;
  101. PRX_CONTEXT pRxContext;
  102. PMRXPROXY_RX_CONTEXT pMRxProxyContext;
  103. //PPROXY_EXCHANGE pExchange = NULL;
  104. ProxyAcquireGlobalSpinLock();
  105. pRxContext = pNotificationContext->pRxContext;
  106. if (pRxContext != NULL) {
  107. // This is a case of successful completion of the change directory
  108. // notification, i.e., the request was not cancelled. In such cases
  109. // prevent all race conditions by modifying the RxContext under lock
  110. // to turn back cancellation request.
  111. pMRxProxyContext = MRxProxyGetMinirdrContext(pRxContext);
  112. //pExchange = pMRxProxyContext->pExchange;
  113. pMRxProxyContext->pCancelContext = NULL;
  114. pNotificationContext->pRxContext = NULL;
  115. }
  116. ProxyReleaseGlobalSpinLock();
  117. // Complete the Context if it was not previously cancelled
  118. if (pRxContext != NULL) {
  119. //PPROXY_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext;
  120. //pResumptionContext = &(pNotificationContext->ResumptionContext);
  121. //pRxContext->StoredStatus = pResumptionContext->FinalStatusFromServer;
  122. Status = RxSetMinirdrCancelRoutine(pRxContext,NULL);
  123. if (Status == STATUS_SUCCESS) {
  124. RxLowIoCompletion(pRxContext);
  125. }
  126. }
  127. #if 0
  128. // Free the associated exchange.
  129. if (pExchange != NULL) {
  130. ProxyCeDereferenceAndDiscardExchange(pExchange);
  131. }
  132. #endif //0
  133. // Free the notification context.
  134. RxFreePool(pNotificationContext);
  135. }
  136. NTSTATUS
  137. MRxProxyNotifyChangeDirectoryCancellation(
  138. PRX_CONTEXT RxContext)
  139. /*++
  140. Routine Description:
  141. This routine is invokde when a directory change notification operation is cancelled.
  142. Arguments:
  143. RxContext - the RDBSS context
  144. Return Value:
  145. NTSTATUS - The return status for the operation
  146. --*/
  147. {
  148. //NTSTATUS Status;
  149. BOOLEAN ChangeDirectoryNotificationCompleted;
  150. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  151. //PPROXY_EXCHANGE pExchange;
  152. PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext;
  153. ProxyAcquireGlobalSpinLock();
  154. pNotificationContext = (PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT)pMRxProxyContext->pCancelContext;
  155. ChangeDirectoryNotificationCompleted = (pNotificationContext == NULL);
  156. if (!ChangeDirectoryNotificationCompleted) {
  157. // This is a case of successful cancellation of the change directory
  158. // notification. In such cases prevent all race conditions by modifying
  159. // the RxContext under lock to prevent successful completion
  160. pNotificationContext->pRxContext = NULL;
  161. //pExchange = pMRxProxyContext->pExchange;
  162. pMRxProxyContext->pCancelContext = NULL;
  163. }
  164. ProxyReleaseGlobalSpinLock();
  165. if (ChangeDirectoryNotificationCompleted) {
  166. // The cancellation is trivial since the request has already been completed
  167. return STATUS_SUCCESS;
  168. }
  169. #if 0 //can't do any of this....no exchanges.........
  170. if (pExchange != NULL) {
  171. UCHAR LastCommandInHeader;
  172. PUCHAR pCommand;
  173. BYTE CancelRequestBuffer[sizeof(PROXY_HEADER) + sizeof(REQ_NT_CANCEL)];
  174. ULONG CancelRequestBufferSize = sizeof(CancelRequestBuffer);
  175. // Build the Cancel request and send it across to the server.
  176. Status = ProxyCeBuildProxyHeader(
  177. pExchange,
  178. CancelRequestBuffer,
  179. CancelRequestBufferSize,
  180. &CancelRequestBufferSize,
  181. &LastCommandInHeader,
  182. &pCommand);
  183. ASSERT(LastCommandInHeader == PROXY_COM_NO_ANDX_COMMAND);
  184. *pCommand = PROXY_COM_NT_CANCEL;
  185. if (Status == RX_MAP_STATUS(SUCCESS)) {
  186. PREQ_NT_CANCEL pCancelRequest = (PREQ_NT_CANCEL)(&CancelRequestBuffer[sizeof(PROXY_HEADER)]);
  187. PMDL pCancelProxyMdl;
  188. ProxyPutUshort(&pCancelRequest->WordCount,0);
  189. pCancelRequest->ByteCount = 0;
  190. CancelRequestBufferSize = sizeof(CancelRequestBuffer);
  191. pCancelProxyMdl = RxAllocateMdl(CancelRequestBuffer,CancelRequestBufferSize);
  192. if (pCancelProxyMdl != NULL) {
  193. RxProbeAndLockPages(pCancelProxyMdl,KernelMode,IoModifyAccess,Status);
  194. if (Status == STATUS_SUCCESS) {
  195. Status = ProxyCeSend(
  196. pExchange,
  197. RXCE_SEND_SYNCHRONOUS,
  198. pCancelProxyMdl,
  199. CancelRequestBufferSize);
  200. MmUnlockPages(pCancelProxyMdl);
  201. }
  202. IoFreeMdl(pCancelProxyMdl);
  203. }
  204. }
  205. ProxyCeDereferenceAndDiscardExchange(pExchange);
  206. }
  207. #endif //0
  208. // Complete the request.
  209. RxContext->StoredStatus = STATUS_CANCELLED;
  210. RxLowIoCompletion(RxContext);
  211. return STATUS_SUCCESS;
  212. }
  213. NTSTATUS
  214. MRxProxyNotifyChangeDirectory(
  215. IN OUT PRX_CONTEXT RxContext)
  216. /*++
  217. Routine Description:
  218. This routine performs a directory change notification operation
  219. Arguments:
  220. RxContext - the RDBSS context
  221. Return Value:
  222. RXSTATUS - The return status for the operation
  223. Notes:
  224. THIS STUFF IS WRONG!!!!!
  225. A directory change notification opertaion is an asychronous operation. It
  226. consists of sending a PROXY requesting change notification whose response is
  227. obtained when the desired change is affected on the server.
  228. Some important points to remember are as follows .....
  229. 1) The PROXY response is not obtained till the desired change is affected on
  230. the server. Therefore an additional MID needs to be reserved on those
  231. connections which permit multiple MID's so that a cancel PROXY can be sent to
  232. the server when a change notification is active.
  233. 2) The Change notification is typical of a long term ( response time
  234. dictated by factors beyond the servers control). Another example is
  235. the query FSCTL operation in CAIRO. For all these operations we initiate
  236. an asychronous transact exchange.
  237. 3) The corresponding LowIo completion routine is invoked asynchronously.
  238. 4) This is an example of an operation for which the MINI RDR has to
  239. register a context for handling cancellations initiated locally.
  240. --*/
  241. {
  242. NTSTATUS Status;
  243. RxCaptureFcb;
  244. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  245. //PPROXYCEDB_SERVER_ENTRY pServerEntry;
  246. //PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext;
  247. #if 0
  248. PBYTE pInputParamBuffer = NULL;
  249. PBYTE pOutputParamBuffer = NULL;
  250. PBYTE pInputDataBuffer = NULL;
  251. PBYTE pOutputDataBuffer = NULL;
  252. ULONG InputParamBufferLength = 0;
  253. ULONG OutputParamBufferLength = 0;
  254. ULONG InputDataBufferLength = 0;
  255. ULONG OutputDataBufferLength = 0;
  256. #endif //0
  257. RxDbgTrace(+1, Dbg, ("MRxNotifyChangeDirectory...Entry\n", 0));
  258. //pServerEntry = ProxyCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  259. //if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_PROXYS)) {
  260. // return STATUS_NOT_SUPPORTED;
  261. //}
  262. #if 0
  263. pNotificationContext =
  264. (PPROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT)
  265. RxAllocatePoolWithTag(
  266. NonPagedPool,
  267. sizeof(PROXY_NOTIFY_CHANGE_DIRECTORY_CONTEXT),
  268. MRXPROXY_FSCTL_POOLTAG);
  269. if (pNotificationContext != NULL) {
  270. PREQ_NOTIFY_CHANGE pNotifyRequest;
  271. PPROXY_TRANSACTION_OPTIONS pTransactionOptions;
  272. PPROXY_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext;
  273. PMRX_PROXY_SRV_OPEN pProxySrvOpen;
  274. RxCaptureFobx;
  275. ASSERT (capFobx != NULL);
  276. Status = MRxProxyDeferredCreate(RxContext);
  277. if (Status==STATUS_SUCCESS) {
  278. pProxySrvOpen = MRxProxyGetSrvOpenExtension(capFobx->pSrvOpen);
  279. ASSERT (!FlagOn(pProxySrvOpen->Flags,PROXY_SRVOPEN_FLAG_NOT_REALLY_OPEN));
  280. pNotificationContext->pRxContext = RxContext;
  281. pNotifyRequest = &(pNotificationContext->NotifyRequest);
  282. pTransactionOptions = &(pNotificationContext->Options);
  283. pResumptionContext = &(pNotificationContext->ResumptionContext);
  284. pNotifyRequest->CompletionFilter = pLowIoContext->ParamsFor.NotifyChangeDirectory.CompletionFilter;
  285. pNotifyRequest->Fid = pProxySrvOpen->Fid;
  286. pNotifyRequest->WatchTree = pLowIoContext->ParamsFor.NotifyChangeDirectory.WatchTree;
  287. pNotifyRequest->Reserved = 0;
  288. OutputDataBufferLength = pLowIoContext->ParamsFor.NotifyChangeDirectory.NotificationBufferLength;
  289. pOutputDataBuffer = pLowIoContext->ParamsFor.NotifyChangeDirectory.pNotificationBuffer;
  290. *pTransactionOptions = RxDefaultTransactionOptions;
  291. pTransactionOptions->NtTransactFunction = NT_TRANSACT_NOTIFY_CHANGE;
  292. pTransactionOptions->TimeoutIntervalInMilliSeconds = PROXYCE_TRANSACTION_TIMEOUT_NOT_USED;
  293. pTransactionOptions->Flags = PROXY_XACT_FLAGS_INDEFINITE_DELAY_IN_RESPONSE;
  294. ProxyCeInitializeAsynchronousTransactionResumptionContext(
  295. pResumptionContext,MRxProxyNotifyChangeDirectoryCompletion,pNotificationContext);
  296. Status = ProxyCeAsynchronousTransact(
  297. RxContext, // the RXContext for the transaction
  298. pTransactionOptions, // transaction options
  299. pNotifyRequest, // the setup buffer
  300. sizeof(REQ_NOTIFY_CHANGE), // setup buffer length
  301. pInputParamBuffer, // Input Param Buffer
  302. InputParamBufferLength, // Input param buffer length
  303. pOutputParamBuffer, // Output param buffer
  304. OutputParamBufferLength, // output param buffer length
  305. pInputDataBuffer, // Input data buffer
  306. InputDataBufferLength, // Input data buffer length
  307. pOutputDataBuffer, // output data buffer
  308. OutputDataBufferLength, // output data buffer length
  309. pResumptionContext // the resumption context
  310. );
  311. if (Status == STATUS_PENDING) {
  312. PMRXPROXY_RX_CONTEXT pMRxProxyContext;
  313. pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  314. pMRxProxyContext->pCancelContext = pNotificationContext;
  315. // Ensure that the appropriate cancel routine is set because this is a long term
  316. // operation and the cancelling mechanism needs to be in place.
  317. Status = RxSetMinirdrCancelRoutine(RxContext,MRxProxyNotifyChangeDirectoryCancellation);
  318. if (Status == STATUS_SUCCESS) {
  319. Status = STATUS_PENDING;
  320. } else if (Status == STATUS_CANCELLED) {
  321. MRxProxyNotifyChangeDirectoryCancellation(RxContext);
  322. Status = STATUS_PENDING;
  323. }
  324. } else {
  325. // On exit from this routine the request would have been completed in all
  326. // the cases. The asynchronous case and synchronous case are folded into
  327. // one async response by returning STATUS_PENDING.
  328. Status = STATUS_PENDING;
  329. }
  330. } else {
  331. NOTHING; //just return the status from the deferred open call
  332. }
  333. } else {
  334. Status = STATUS_INSUFFICIENT_RESOURCES;
  335. }
  336. #endif //0
  337. Status = STATUS_NOT_SUPPORTED;
  338. RxDbgTrace(-1, Dbg, ("MRxProxyNotifyChangeDirectory -> %08lx\n", Status ));
  339. return Status;
  340. }
  341. NTSTATUS
  342. MRxProxyFsControl(PRX_CONTEXT RxContext)
  343. /*++
  344. Routine Description:
  345. This routine handles all the FSCTL's
  346. Arguments:
  347. RxContext - the RDBSS context
  348. Return Value:
  349. RXSTATUS - The return status for the operation
  350. Notes:
  351. Remoting of FSCTL's is permitted only to NT servers.
  352. --*/
  353. {
  354. NTSTATUS Status;
  355. RxCaptureFobx;
  356. //PMRX_PROXY_SRV_OPEN pProxySrvOpen;
  357. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  358. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  359. PAGED_CODE();
  360. RxDbgTrace(+1, Dbg, ("MRxProxyFsControl...Entry FsControlCode(%lx)\n", FsControlCode));
  361. Status = STATUS_NOT_IMPLEMENTED;
  362. RxDbgTrace(-1, Dbg, ("MRxProxyFsControl...Exit\n"));
  363. return Status;
  364. }
  365. #if DBG
  366. NTSTATUS
  367. MRxProxyTestForLowIoIoctl(
  368. IN PRX_CONTEXT RxContext
  369. )
  370. {
  371. NTSTATUS Status = STATUS_SUCCESS;
  372. RxCaptureFcb;RxCaptureFobx;
  373. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  374. PSZ Buffer = (PSZ)(LowIoContext->ParamsFor.IoCtl.pInputBuffer);
  375. ULONG OutputBufferLength = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
  376. ULONG InputBufferLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  377. UNICODE_STRING u;
  378. PUNICODE_STRING FileName = &capFcb->AlreadyPrefixedName;
  379. ULONG ReturnLength;
  380. ReturnLength = OutputBufferLength;
  381. if (ReturnLength > FileName->Length) {
  382. ReturnLength = FileName->Length;
  383. }
  384. RxDbgTrace(0, Dbg,
  385. ("Here in MRxProxyTestForLowIoIoctl %s, obl = %08lx, rl=%08lx\n", Buffer, OutputBufferLength, ReturnLength));
  386. //return an obvious string to make sure that darryl is copying the results out correctly
  387. //BUGBUG need to check the lengths i.e. need outputl<=inputl; also need to check that count and buffer
  388. // are aligned for wchar
  389. RtlCopyMemory(Buffer,FileName->Buffer,ReturnLength);
  390. u.Buffer = (PWCHAR)(Buffer);
  391. u.Length = u.MaximumLength = (USHORT)ReturnLength;
  392. RtlUpcaseUnicodeString(&u,&u,FALSE);
  393. RxContext->InformationToReturn =
  394. //LowIoContext->ParamsFor.IoCtl.OutputBufferLength =
  395. ReturnLength;
  396. return(Status);
  397. }
  398. #endif //if DBG
  399. NTSTATUS
  400. MRxProxyIoCtl(
  401. IN OUT PRX_CONTEXT RxContext)
  402. /*++
  403. Routine Description:
  404. This routine performs an IOCTL operation. Currently, no calls are remoted; in fact, the only call accepted
  405. is for debugging.
  406. Arguments:
  407. RxContext - the RDBSS context
  408. Return Value:
  409. RXSTATUS - The return status for the operation
  410. Notes:
  411. --*/
  412. {
  413. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  414. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  415. ULONG IoControlCode = pLowIoContext->ParamsFor.IoCtl.IoControlCode;
  416. RxDbgTrace(+1, Dbg, ("MRxProxyIoCtl...\n", 0));
  417. RxDbgTrace( 0, Dbg, ("MRxProxyIoCtl = %08lx\n", IoControlCode));
  418. switch (IoControlCode) {
  419. #if DBG
  420. case IOCTL_LMMR_TESTLOWIO:
  421. Status = MRxProxyTestForLowIoIoctl(RxContext);
  422. break;
  423. #endif //if DBG
  424. default:
  425. break;
  426. }
  427. RxDbgTrace(-1, Dbg, ("MRxProxyIoCtl -> %08lx\n", Status ));
  428. return Status;
  429. }
  430.