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.

326 lines
11 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. chngnote.c
  5. Abstract:
  6. This module will someday implement change notify. currently it just returns
  7. not_implemented. when we have async upcalls, we will revisit this.
  8. Author:
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "webdav.h"
  14. //
  15. // The local debug trace level
  16. //
  17. //BUGBUG we need to implement change directory........
  18. typedef struct _UMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT_ {
  19. PRX_CONTEXT pRxContext;
  20. //REQ_NOTIFY_CHANGE NotifyRequest;
  21. } UMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT, *PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT;
  22. VOID
  23. UMRxNotifyChangeDirectoryCompletion(
  24. PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext)
  25. /*++
  26. Routine Description:
  27. This routine is invokde when a directory change notification operation is completed
  28. Arguments:
  29. RxContext - the RDBSS context
  30. Return Value:
  31. RXSTATUS - The return status for the operation
  32. Notes:
  33. This routine will always be called. This is true even if the change directory
  34. notification is cancelled. In such cases the memory allocated is freed without
  35. any inteaction with the wrapped. In cases os successful directory change
  36. notification completion the appropriate completion routine is invoked and the
  37. RxContext modified to prevent any cancellation from proceeding further.
  38. --*/
  39. {
  40. NTSTATUS Status;
  41. PRX_CONTEXT pRxContext;
  42. PUMRX_RX_CONTEXT pUMRxContext;
  43. MRxDAVAcquireGlobalSpinLock();
  44. pRxContext = pNotificationContext->pRxContext;
  45. if (pRxContext != NULL) {
  46. // This is a case of successful completion of the change directory
  47. // notification, i.e., the request was not cancelled. In such cases
  48. // prevent all race conditions by modifying the RxContext under lock
  49. // to turn back cancellation request.
  50. pUMRxContext = UMRxGetMinirdrContext(pRxContext);
  51. pUMRxContext->pCancelContext = NULL;
  52. pNotificationContext->pRxContext = NULL;
  53. }
  54. MRxDAVReleaseGlobalSpinLock();
  55. // Complete the Context if it was not previously cancelled
  56. if (pRxContext != NULL) {
  57. //pResumptionContext = &(pNotificationContext->ResumptionContext);
  58. //pRxContext->StoredStatus = pResumptionContext->FinalStatusFromServer;
  59. Status = RxSetMinirdrCancelRoutine(pRxContext,NULL);
  60. if (Status == STATUS_SUCCESS) {
  61. RxLowIoCompletion(pRxContext);
  62. }
  63. }
  64. #if 0
  65. // Free the associated exchange.
  66. if (pExchange != NULL) {
  67. UMRxCeDereferenceAndDiscardExchange(pExchange);
  68. }
  69. #endif //0
  70. // Free the notification context.
  71. RxFreePool(pNotificationContext);
  72. }
  73. NTSTATUS
  74. UMRxNotifyChangeDirectoryCancellation(
  75. PRX_CONTEXT RxContext)
  76. /*++
  77. Routine Description:
  78. This routine is invokde when a directory change notification operation is cancelled.
  79. Arguments:
  80. RxContext - the RDBSS context
  81. Return Value:
  82. NTSTATUS - The return status for the operation
  83. --*/
  84. {
  85. //NTSTATUS Status;
  86. BOOLEAN ChangeDirectoryNotificationCompleted;
  87. PUMRX_RX_CONTEXT pUMRxContext = UMRxGetMinirdrContext(RxContext);
  88. PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext;
  89. MRxDAVAcquireGlobalSpinLock();
  90. pNotificationContext = (PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT)pUMRxContext->pCancelContext;
  91. ChangeDirectoryNotificationCompleted = (pNotificationContext == NULL);
  92. if (!ChangeDirectoryNotificationCompleted) {
  93. // This is a case of successful cancellation of the change directory
  94. // notification. In such cases prevent all race conditions by modifying
  95. // the RxContext under lock to prevent successful completion
  96. pNotificationContext->pRxContext = NULL;
  97. pUMRxContext->pCancelContext = NULL;
  98. }
  99. MRxDAVReleaseGlobalSpinLock();
  100. if (ChangeDirectoryNotificationCompleted) {
  101. // The cancellation is trivial since the request has already been completed
  102. return STATUS_SUCCESS;
  103. }
  104. // Complete the request.
  105. RxContext->StoredStatus = STATUS_CANCELLED;
  106. RxLowIoCompletion(RxContext);
  107. return STATUS_SUCCESS;
  108. }
  109. NTSTATUS
  110. UMRxNotifyChangeDirectory(
  111. IN OUT PRX_CONTEXT RxContext)
  112. /*++
  113. Routine Description:
  114. This routine performs a directory change notification operation
  115. Arguments:
  116. RxContext - the RDBSS context
  117. Return Value:
  118. RXSTATUS - The return status for the operation
  119. Notes:
  120. BUGBUG THIS STUFF IS WRONG!!!!! It refers to the smbmini implementation.
  121. i am leaving most stuff in to guide the implementation for the reflector.
  122. A directory change notification opertaion is an asychronous operation. It
  123. consists of sending a change notification whose response is
  124. obtained when the desired change is affected on the server.
  125. Some important points to remember are as follows .....
  126. 1) The response is not obtained till the desired change is affected on
  127. the server. Therefore an additional MID needs to be reserved on those
  128. connections which permit multiple MID's so that a cancel can be sent to
  129. the server when a change notification is active.
  130. 2) The Change notification is typical of a long term ( response time
  131. dictated by factors beyond the servers control). Another example is
  132. the query FSCTL operation in CAIRO. For all these operations we initiate
  133. an asychronous transact exchange.
  134. 3) The corresponding LowIo completion routine is invoked asynchronously.
  135. 4) This is an example of an operation for which the MINI RDR has to
  136. register a context for handling cancellations initiated locally.
  137. --*/
  138. {
  139. NTSTATUS Status;
  140. RxCaptureFcb;
  141. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  142. //PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext;
  143. #if 0
  144. PBYTE pInputParamBuffer = NULL;
  145. PBYTE pOutputParamBuffer = NULL;
  146. PBYTE pInputDataBuffer = NULL;
  147. PBYTE pOutputDataBuffer = NULL;
  148. ULONG InputParamBufferLength = 0;
  149. ULONG OutputParamBufferLength = 0;
  150. ULONG InputDataBufferLength = 0;
  151. ULONG OutputDataBufferLength = 0;
  152. #endif //0
  153. // RxDbgTrace(+1, Dbg, ("MRxNotifyChangeDirectory...Entry\n", 0));
  154. #if 0
  155. pNotificationContext =
  156. (PUMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT)
  157. RxAllocatePoolWithTag(
  158. NonPagedPool,
  159. sizeof(UMRX_NOTIFY_CHANGE_DIRECTORY_CONTEXT),
  160. DAV_FSCTL_POOLTAG);
  161. if (pNotificationContext != NULL) {
  162. PREQ_NOTIFY_CHANGE pNotifyRequest;
  163. PUMRX_SRV_OPEN pUMRxSrvOpen;
  164. IF_DEBUG {
  165. RxCaptureFobx;
  166. ASSERT (capFobx != NULL);
  167. ASSERT (capFobx->pSrvOpen == RxContext->pRelevantSrvOpen); //ok
  168. }
  169. Status = UMRxDeferredCreate(RxContext);
  170. if (Status==STATUS_SUCCESS) {
  171. pUMRxSrvOpen = UMRxGetSrvOpenExtension(RxContext->pRelevantSrvOpen);
  172. pNotificationContext->pRxContext = RxContext;
  173. pNotifyRequest = &(pNotificationContext->NotifyRequest);
  174. pTransactionOptions = &(pNotificationContext->Options);
  175. pResumptionContext = &(pNotificationContext->ResumptionContext);
  176. pNotifyRequest->CompletionFilter = pLowIoContext->ParamsFor.NotifyChangeDirectory.CompletionFilter;
  177. pNotifyRequest->Fid = pUMRxSrvOpen->Fid;
  178. pNotifyRequest->WatchTree = pLowIoContext->ParamsFor.NotifyChangeDirectory.WatchTree;
  179. pNotifyRequest->Reserved = 0;
  180. OutputDataBufferLength = pLowIoContext->ParamsFor.NotifyChangeDirectory.NotificationBufferLength;
  181. pOutputDataBuffer = pLowIoContext->ParamsFor.NotifyChangeDirectory.pNotificationBuffer;
  182. *pTransactionOptions = RxDefaultTransactionOptions;
  183. pTransactionOptions->NtTransactFunction = NT_TRANSACT_NOTIFY_CHANGE;
  184. pTransactionOptions->TimeoutIntervalInMilliSeconds = SMBCE_TRANSACTION_TIMEOUT_NOT_USED;
  185. pTransactionOptions->Flags = SMB_XACT_FLAGS_INDEFINITE_DELAY_IN_RESPONSE;
  186. UMRxCeInitializeAsynchronousTransactionResumptionContext(
  187. pResumptionContext,UMRxNotifyChangeDirectoryCompletion,pNotificationContext);
  188. Status = UMRxCeAsynchronousTransact(
  189. RxContext, // the RXContext for the transaction
  190. pTransactionOptions, // transaction options
  191. pNotifyRequest, // the setup buffer
  192. sizeof(REQ_NOTIFY_CHANGE), // setup buffer length
  193. pInputParamBuffer, // Input Param Buffer
  194. InputParamBufferLength, // Input param buffer length
  195. pOutputParamBuffer, // Output param buffer
  196. OutputParamBufferLength, // output param buffer length
  197. pInputDataBuffer, // Input data buffer
  198. InputDataBufferLength, // Input data buffer length
  199. pOutputDataBuffer, // output data buffer
  200. OutputDataBufferLength, // output data buffer length
  201. pResumptionContext // the resumption context
  202. );
  203. if (Status == STATUS_PENDING) {
  204. PUMRX_RX_CONTEXT pUMRxContext;
  205. pUMRxContext = UMRxGetMinirdrContext(RxContext);
  206. pUMRxContext->pCancelContext = pNotificationContext;
  207. // Ensure that the appropriate cancel routine is set because this is a long term
  208. // operation and the cancelling mechanism needs to be in place.
  209. Status = RxSetMinirdrCancelRoutine(RxContext,UMRxNotifyChangeDirectoryCancellation);
  210. if (Status == STATUS_SUCCESS) {
  211. Status = STATUS_PENDING;
  212. } else if (Status == STATUS_CANCELLED) {
  213. UMRxNotifyChangeDirectoryCancellation(RxContext);
  214. Status = STATUS_PENDING;
  215. }
  216. } else {
  217. // On exit from this routine the request would have been completed in all
  218. // the cases. The asynchronous case and synchronous case are folded into
  219. // one async response by returning STATUS_PENDING.
  220. Status = STATUS_PENDING;
  221. }
  222. } else {
  223. NOTHING; //just return the status from the deferred open call
  224. }
  225. } else {
  226. Status = STATUS_INSUFFICIENT_RESOURCES;
  227. }
  228. #endif //0
  229. Status = STATUS_NOT_SUPPORTED;
  230. // RxDbgTrace(-1, Dbg, ("UMRxNotifyChangeDirectory -> %08lx\n", Status ));
  231. return Status;
  232. }
  233.