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.

1939 lines
61 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cancel.c
  5. Abstract:
  6. This module implements the routines relating to the cancel logic in the
  7. DAV MiniRedir.
  8. Author:
  9. Rohan Kumar [RohanK] 10-April-2001
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "ntverp.h"
  15. #include "netevent.h"
  16. #include "nvisible.h"
  17. #include "webdav.h"
  18. #include "ntddmup.h"
  19. #include "rxdata.h"
  20. #include "fsctlbuf.h"
  21. //
  22. // The timeout values for various operations used by the MiniRedir. If an
  23. // operation is not completed within the timeout value specified for it, is
  24. // cancelled. The user can set the value to 0xffffffff to disable the
  25. // timeout/cancel logic. In other words, if the timeout value is 0xffffffff,
  26. // the requests will never timeout.
  27. //
  28. ULONG CreateRequestTimeoutValueInSec;
  29. ULONG CreateVNetRootRequestTimeoutValueInSec;
  30. ULONG QueryDirectoryRequestTimeoutValueInSec;
  31. ULONG CloseRequestTimeoutValueInSec;
  32. ULONG CreateSrvCallRequestTimeoutValueInSec;
  33. ULONG FinalizeSrvCallRequestTimeoutValueInSec;
  34. ULONG FinalizeFobxRequestTimeoutValueInSec;
  35. ULONG FinalizeVNetRootRequestTimeoutValueInSec;
  36. ULONG ReNameRequestTimeoutValueInSec;
  37. ULONG SetFileInfoRequestTimeoutValueInSec;
  38. ULONG QueryFileInfoRequestTimeoutValueInSec;
  39. ULONG QueryVolumeInfoRequestTimeoutValueInSec;
  40. ULONG LockRefreshRequestTimeoutValueInSec;
  41. //
  42. // The timer thread wakes up every "TimerThreadSleepTimeInSec" and cancels all
  43. // the requests which haven't completed in their specified timeout value. This
  44. // value is set to the min of the timeout values of all the requests mentioned
  45. // above.
  46. //
  47. ULONG TimerThreadSleepTimeInSec;
  48. //
  49. // The timer object used by the timer thread that cancels the requests which
  50. // have not completed in a specified time.
  51. //
  52. KTIMER DavTimerObject;
  53. //
  54. // This is used to indicate the timer thread to shutdown. When the system is
  55. // being shutdown this is set to TRUE. MRxDAVTimerThreadLock is the resource
  56. // used to gain access to this variable.
  57. //
  58. BOOL TimerThreadShutDown;
  59. ERESOURCE MRxDAVTimerThreadLock;
  60. //
  61. // The handle of the timer thread that is created using PsCreateSystemThread
  62. // is stored this global.
  63. //
  64. HANDLE TimerThreadHandle;
  65. //
  66. // This event is signalled by the timer thread right before its going to
  67. // terminate itself.
  68. //
  69. KEVENT TimerThreadEvent;
  70. //
  71. // If QueueLockRefreshWorkItem is TRUE, the TimerThread (which cancels all the
  72. // AsyncEngineContexts that haven't completed in a specified time) queues a
  73. // WorkItem to refresh the locks. After the WorkItem has been queued the value
  74. // of QueueLockRefreshWorkItem is set to FALSE. Once the worker thread is
  75. // done refreshing all the locks, it resets this value to TRUE. We have a
  76. // corresponding lock QueueLockRefreshWorkItemLock to synchronize access to
  77. // QueueLockRefreshWorkItem.
  78. //
  79. BOOL QueueLockRefreshWorkItem;
  80. ERESOURCE QueueLockRefreshWorkItemLock;
  81. //
  82. // The WorkQueueItem used in the MRxDAVContextTimerThread function to refresh
  83. // the LOCKs taken by this client.
  84. //
  85. RX_WORK_QUEUE_ITEM LockRefreshWorkQueueItem;
  86. NTSTATUS
  87. MRxDAVCancelTheContext(
  88. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  89. BOOL UserInitiatedCancel
  90. );
  91. NTSTATUS
  92. MRxDAVCompleteTheCancelledRequest(
  93. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  94. BOOL UserInitiatedCancel
  95. );
  96. NTSTATUS
  97. MRxDAVHandleGeneralCancellation(
  98. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  99. BOOL UserInitiatedCancel
  100. );
  101. NTSTATUS
  102. MRxDAVHandleQueryDirCancellation(
  103. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  104. BOOL UserInitiatedCancel
  105. );
  106. NTSTATUS
  107. MRxDAVHandleCloseSrvOpenCancellation(
  108. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  109. BOOL UserInitiatedCancel
  110. );
  111. NTSTATUS
  112. MRxDAVHandleSetFileInfoCancellation(
  113. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  114. BOOL UserInitiatedCancel
  115. );
  116. NTSTATUS
  117. MRxDAVHandleCreateCancellation(
  118. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  119. BOOL UserInitiatedCancel
  120. );
  121. NTSTATUS
  122. MRxDAVHandleCreateSrvCallCancellation(
  123. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  124. BOOL UserInitiatedCancel
  125. );
  126. NTSTATUS
  127. MRxDAVHandleSrvCallFinalizeCancellation(
  128. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  129. BOOL UserInitiatedCancel
  130. );
  131. NTSTATUS
  132. MRxDAVHandleCreateVNetRootCancellation(
  133. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  134. BOOL UserInitiatedCancel
  135. );
  136. NTSTATUS
  137. MRxDAVHandleFinalizeVNetRootCancellation(
  138. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  139. BOOL UserInitiatedCancel
  140. );
  141. NTSTATUS
  142. MRxDAVHandleCleanupFobxCancellation(
  143. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  144. BOOL UserInitiatedCancel
  145. );
  146. NTSTATUS
  147. MRxDAVHandleRenameCancellation(
  148. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  149. BOOL UserInitiatedCancel
  150. );
  151. NTSTATUS
  152. MRxDAVHandleQueryFileInfoCancellation(
  153. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  154. BOOL UserInitiatedCancel
  155. );
  156. NTSTATUS
  157. MRxDAVHandleLockRefreshCancellation(
  158. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  159. BOOL UserInitiatedCancel
  160. );
  161. VOID
  162. MRxDAVRefreshTheServerLocks(
  163. PVOID DummyContext
  164. );
  165. NTSTATUS
  166. MRxDAVRefreshTheServerLocksContinuation(
  167. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  168. );
  169. NTSTATUS
  170. MRxDAVFormatUserModeRefreshTheServerLockRequest(
  171. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  172. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  173. IN ULONG WorkItemLength,
  174. OUT PULONG_PTR ReturnedLength
  175. );
  176. BOOL
  177. MRxDAVPrecompleteUserModeRefreshTheServerLockRequest(
  178. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  179. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  180. ULONG WorkItemLength,
  181. BOOL OperationCancelled
  182. );
  183. //
  184. // Implementation of functions begins here.
  185. //
  186. NTSTATUS
  187. MRxDAVCancelRoutine(
  188. PRX_CONTEXT RxContext
  189. )
  190. /*++
  191. Routine Description:
  192. This routine initiates the cancellation of an I/O request.
  193. Arguments:
  194. RxContext - The RX_CONTEXT instance which needs to be cancelled.
  195. Return Value:
  196. NTSTATUS - The return status for the operation.
  197. --*/
  198. {
  199. NTSTATUS NtStatus = STATUS_SUCCESS;
  200. PLIST_ENTRY listEntry = NULL;
  201. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext = NULL;
  202. BOOL lockAcquired = FALSE, contextFound = FALSE;
  203. DavDbgTrace(DAV_TRACE_DETAIL,
  204. ("%ld: MRxDAVCancelRoutine. RxContext = %08lx\n",
  205. PsGetCurrentThreadId(), RxContext));
  206. ExAcquireResourceExclusiveLite(&(UMRxAsyncEngineContextListLock), TRUE);
  207. lockAcquired = TRUE;
  208. listEntry = UMRxAsyncEngineContextList.Flink;
  209. while ( listEntry != &(UMRxAsyncEngineContextList) ) {
  210. //
  211. // Get the pointer to the UMRX_ASYNCENGINE_CONTEXT structure.
  212. //
  213. AsyncEngineContext = CONTAINING_RECORD(listEntry,
  214. UMRX_ASYNCENGINE_CONTEXT,
  215. ActiveContextsListEntry);
  216. listEntry = listEntry->Flink;
  217. //
  218. // Check to see if this entry is for the RxContext in question.
  219. //
  220. if (AsyncEngineContext->RxContext == RxContext) {
  221. DavDbgTrace(DAV_TRACE_DETAIL,
  222. ("%ld: MRxDAVCancelRoutine: RxContext: %08lx FOUND\n",
  223. PsGetCurrentThreadId(), RxContext));
  224. contextFound = TRUE;
  225. break;
  226. }
  227. }
  228. if (!contextFound) {
  229. DavDbgTrace(DAV_TRACE_DETAIL,
  230. ("%ld: MRxDAVCancelTheContext: RxContext: %08lx NOT FOUND\n",
  231. PsGetCurrentThreadId(), RxContext));
  232. goto EXIT_THE_FUNCTION;
  233. }
  234. NtStatus = MRxDAVCancelTheContext(AsyncEngineContext, TRUE);
  235. EXIT_THE_FUNCTION:
  236. //
  237. // If we acquired the UMRxAsyncEngineContextListLock, then we need to
  238. // release it now.
  239. //
  240. if (lockAcquired) {
  241. ExReleaseResourceLite(&(UMRxAsyncEngineContextListLock));
  242. lockAcquired = FALSE;
  243. }
  244. DavDbgTrace(DAV_TRACE_DETAIL,
  245. ("%ld: MRxDAVCancelTheContext: Returning NtStatus = %08lx\n",
  246. PsGetCurrentThreadId(), NtStatus));
  247. return NtStatus;
  248. }
  249. VOID
  250. MRxDAVContextTimerThread(
  251. PVOID DummyContext
  252. )
  253. /*++
  254. Routine Description:
  255. This timer thread is created with this routine. The thread waits on a timer
  256. object which gets signalled TimerThreadSleepTimeInSec after it has been
  257. inserted into the timer queue.
  258. Arguments:
  259. DummyContext - A dummy context that is supplied.
  260. Return Value:
  261. None.
  262. --*/
  263. {
  264. NTSTATUS NtStatus = STATUS_SUCCESS;
  265. LONGLONG DueTimeInterval;
  266. LONG CopyTheRequestTimeValue;
  267. BOOLEAN setTimer = FALSE, lockAcquired = FALSE;
  268. CopyTheRequestTimeValue = TimerThreadSleepTimeInSec;
  269. do {
  270. //
  271. // If TimerThreadShutDown is set to TRUE, it means that the system is
  272. // being shutdown. The job of this thread is done. We check here after
  273. // we have gone through the context list and before we restart the wait.
  274. // We also check this below as soon as the DavTimerObject is signalled.
  275. //
  276. ExAcquireResourceExclusiveLite(&(MRxDAVTimerThreadLock), TRUE);
  277. lockAcquired = TRUE;
  278. if (TimerThreadShutDown) {
  279. break;
  280. }
  281. ExReleaseResourceLite(&(MRxDAVTimerThreadLock));
  282. lockAcquired = FALSE;
  283. //
  284. // We set the DueTimeInterval to be -ve TimerThreadSleepTimeInSec in 100
  285. // nano seconds. This is because this tells KeSetTimerEx that the
  286. // expiration time is relative to the current system time.
  287. //
  288. DueTimeInterval = ( -CopyTheRequestTimeValue * 1000 * 1000 * 10 );
  289. //
  290. // Call KeSetTimerEx to insert the TimerObject in the system's timer
  291. // queue. Also, the return value should be FALSE since this timer
  292. // should not exist in the system queue.
  293. //
  294. setTimer = KeSetTimerEx(&(DavTimerObject), *(PLARGE_INTEGER)&(DueTimeInterval), 0, NULL);
  295. ASSERT(setTimer == FALSE);
  296. //
  297. // Wait for the timer object to be signalled. This call should only
  298. // return if the wait has been satisfied, which implies that the return
  299. // value is STATUS_SUCCESS.
  300. //
  301. NtStatus = KeWaitForSingleObject(&(DavTimerObject),
  302. Executive,
  303. KernelMode,
  304. FALSE,
  305. NULL);
  306. ASSERT(NtStatus == STATUS_SUCCESS);
  307. //
  308. // If TimerThreadShutDown is set to TRUE, it means that the system is
  309. // being shutdown. The job of this thread is done. We check as soon as
  310. // the DavTimerObject is signalled. We also check this above as soon
  311. // as we complete cycling through the context list.
  312. //
  313. ExAcquireResourceExclusiveLite(&(MRxDAVTimerThreadLock), TRUE);
  314. lockAcquired = TRUE;
  315. if (TimerThreadShutDown) {
  316. break;
  317. }
  318. ExReleaseResourceLite(&(MRxDAVTimerThreadLock));
  319. lockAcquired = FALSE;
  320. //
  321. // Now call MRxDAVTimeOutTheContexts which cycles through all the
  322. // currently active contexts and cancels the ones that have been hanging
  323. // around for more than their timeout values.
  324. //
  325. MRxDAVTimeOutTheContexts(FALSE);
  326. //
  327. // Now call MRxDAVCleanUpTheLockConflictList to delete all the expired
  328. // entries from the global LockConflictEntryList.
  329. //
  330. MRxDAVCleanUpTheLockConflictList(FALSE);
  331. //
  332. // We now post a workitem to a system worker thread. This calls the
  333. // function MRxDAVRefreshTheServerLocks which refreshes all the
  334. // currently active LOCKs. This is done if QueueLockRefreshWorkItem
  335. // is TRUE. After posting the workitem, its set to FALSE. Once the
  336. // workitem is dequeued and the locks are refreshed, its reset to
  337. // TRUE by the worker thread.
  338. //
  339. ExAcquireResourceExclusiveLite(&(QueueLockRefreshWorkItemLock), TRUE);
  340. if (QueueLockRefreshWorkItem) {
  341. NtStatus = RxPostToWorkerThread((PRDBSS_DEVICE_OBJECT)MRxDAVDeviceObject,
  342. CriticalWorkQueue,
  343. &(LockRefreshWorkQueueItem),
  344. MRxDAVRefreshTheServerLocks,
  345. NULL);
  346. ASSERT(NtStatus == STATUS_SUCCESS);
  347. QueueLockRefreshWorkItem = FALSE;
  348. }
  349. ExReleaseResourceLite(&(QueueLockRefreshWorkItemLock));
  350. } while (TRUE);
  351. //
  352. // If the lock is still acquired, we need to release it.
  353. //
  354. if (lockAcquired) {
  355. ExReleaseResourceLite(&(MRxDAVTimerThreadLock));
  356. lockAcquired = FALSE;
  357. }
  358. //
  359. // Set the timer thread event signalling that the timer thread is done
  360. // with the MRxDAVTimerThreadLock and that it can be deleted.
  361. //
  362. KeSetEvent(&(TimerThreadEvent), 0, FALSE);
  363. //
  364. // Close the thread handle to remove the reference on the object. We need
  365. // to do this before we call PsTerminateSystemThread.
  366. //
  367. ZwClose(TimerThreadHandle);
  368. //
  369. // Terminate this thread since we are going to shutdown now.
  370. //
  371. PsTerminateSystemThread(STATUS_SUCCESS);
  372. return;
  373. }
  374. VOID
  375. MRxDAVTimeOutTheContexts(
  376. BOOL WindDownAllContexts
  377. )
  378. /*++
  379. Routine Description:
  380. This routine is called by the thread that wakes up every "X" minutes to see
  381. if some AsyncEngineContext has been hanging around in the active contexts
  382. list for more than "X" minutes. If it finds some such context, it just cancels
  383. the operation. The value "X" is read from the registry and is stored in the
  384. global variable MRxDAVRequestTimeoutValueInSec at driver init time. This value
  385. defaults to 10 min. In other words, if an operation has not completed in "X"
  386. minutes, it is cancelled. The user can set this value to 0xffffffff to turn
  387. off the timeout.
  388. It can also be called by the thread that is trying to complete all the
  389. requests and stop the MiniRedir. This happens when the WebClient service
  390. is being stopped.
  391. Arguments:
  392. WindDownAllContexts - If this is set to TRUE, then all the contexts are
  393. cancelled no matter when they were added to the list.
  394. This is set to FALSE by the timer thread and to TRUE
  395. by the thread that is stopping the MiniRedir.
  396. Return Value:
  397. None.
  398. --*/
  399. {
  400. NTSTATUS NtStatus = STATUS_SUCCESS;
  401. PLIST_ENTRY listEntry = NULL;
  402. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext = NULL;
  403. PWEBDAV_CONTEXT DavContext = NULL;
  404. BOOL lockAcquired = FALSE;
  405. LARGE_INTEGER CurrentSystemTickCount, TickCountDifference;
  406. LARGE_INTEGER RequestTimeoutValueInTickCount;
  407. ULONG RequestTimeoutValueInSec = 0;
  408. ExAcquireResourceExclusiveLite(&(UMRxAsyncEngineContextListLock), TRUE);
  409. lockAcquired = TRUE;
  410. listEntry = UMRxAsyncEngineContextList.Flink;
  411. while ( listEntry != &(UMRxAsyncEngineContextList) ) {
  412. //
  413. // Get the pointer to the UMRX_ASYNCENGINE_CONTEXT structure.
  414. //
  415. AsyncEngineContext = CONTAINING_RECORD(listEntry,
  416. UMRX_ASYNCENGINE_CONTEXT,
  417. ActiveContextsListEntry);
  418. listEntry = listEntry->Flink;
  419. DavContext = (PWEBDAV_CONTEXT)AsyncEngineContext;
  420. if (!WindDownAllContexts) {
  421. switch (DavContext->EntryPoint) {
  422. case DAV_MINIRDR_ENTRY_FROM_CREATE:
  423. RequestTimeoutValueInSec = CreateRequestTimeoutValueInSec;
  424. break;
  425. case DAV_MINIRDR_ENTRY_FROM_CLEANUPFOBX:
  426. RequestTimeoutValueInSec = FinalizeFobxRequestTimeoutValueInSec;
  427. break;
  428. case DAV_MINIRDR_ENTRY_FROM_CREATESRVCALL:
  429. RequestTimeoutValueInSec = CreateSrvCallRequestTimeoutValueInSec;
  430. break;
  431. case DAV_MINIRDR_ENTRY_FROM_CREATEVNETROOT:
  432. RequestTimeoutValueInSec = CreateVNetRootRequestTimeoutValueInSec;
  433. break;
  434. case DAV_MINIRDR_ENTRY_FROM_FINALIZESRVCALL:
  435. RequestTimeoutValueInSec = FinalizeSrvCallRequestTimeoutValueInSec;
  436. break;
  437. case DAV_MINIRDR_ENTRY_FROM_FINALIZEVNETROOT:
  438. RequestTimeoutValueInSec = FinalizeVNetRootRequestTimeoutValueInSec;
  439. break;
  440. case DAV_MINIRDR_ENTRY_FROM_CLOSESRVOPEN:
  441. RequestTimeoutValueInSec = CloseRequestTimeoutValueInSec;
  442. break;
  443. case DAV_MINIRDR_ENTRY_FROM_RENAME:
  444. RequestTimeoutValueInSec = ReNameRequestTimeoutValueInSec;
  445. break;
  446. case DAV_MINIRDR_ENTRY_FROM_QUERYDIR:
  447. RequestTimeoutValueInSec = QueryDirectoryRequestTimeoutValueInSec;
  448. break;
  449. case DAV_MINIRDR_ENTRY_FROM_SETFILEINFORMATION:
  450. RequestTimeoutValueInSec = SetFileInfoRequestTimeoutValueInSec;
  451. break;
  452. case DAV_MINIRDR_ENTRY_FROM_QUERYFILEINFORMATION:
  453. RequestTimeoutValueInSec = QueryFileInfoRequestTimeoutValueInSec;
  454. break;
  455. case DAV_MINIRDR_ENTRY_FROM_QUERYVOLUMEINFORMATION:
  456. RequestTimeoutValueInSec = QueryVolumeInfoRequestTimeoutValueInSec;
  457. break;
  458. case DAV_MINIRDR_ENTRY_FROM_REFRESHTHELOCK:
  459. RequestTimeoutValueInSec = LockRefreshRequestTimeoutValueInSec;
  460. break;
  461. default:
  462. DbgPrint("MRxDAVTimeOutTheContexts: EntryPoint = %d\n", DavContext->EntryPoint);
  463. ASSERT(FALSE);
  464. }
  465. //
  466. // Calculate the timeout value in TickCount (100 nano seconds) using
  467. // the timeout value in seconds) which we got from above. Step1 below
  468. // calculates the number of ticks that happen in one second. Step2
  469. // below calculates the number of ticks in RequestTimeoutValueInSec.
  470. //
  471. RequestTimeoutValueInTickCount.QuadPart = ( (1000 * 1000 * 10) / KeQueryTimeIncrement() );
  472. RequestTimeoutValueInTickCount.QuadPart *= RequestTimeoutValueInSec;
  473. KeQueryTickCount( &(CurrentSystemTickCount) );
  474. //
  475. // Get the time elapsed (in system tick counts) since the time this
  476. // AsyncEngineContext was created.
  477. //
  478. TickCountDifference.QuadPart = (CurrentSystemTickCount.QuadPart - AsyncEngineContext->CreationTimeInTickCount.QuadPart);
  479. //
  480. // If the amount of time that has elapsed since this context was added
  481. // to the list is greater than the timeout value, then cancel the
  482. // request.
  483. //
  484. if (TickCountDifference.QuadPart > RequestTimeoutValueInTickCount.QuadPart) {
  485. NtStatus = MRxDAVCancelTheContext(AsyncEngineContext, FALSE);
  486. }
  487. } else {
  488. //
  489. // If we were asked to wind down all the contexts then we cancel
  490. // every request no matter when it was inserted into the active
  491. // context list.
  492. //
  493. NtStatus = MRxDAVCancelTheContext(AsyncEngineContext, FALSE);
  494. }
  495. }
  496. if (lockAcquired) {
  497. ExReleaseResourceLite(&(UMRxAsyncEngineContextListLock));
  498. lockAcquired = FALSE;
  499. }
  500. return;
  501. }
  502. NTSTATUS
  503. MRxDAVCancelTheContext(
  504. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  505. BOOL UserInitiatedCancel
  506. )
  507. /*++
  508. Routine Description:
  509. This routine handles the cancellation of an I/O request. The caller of this
  510. routine needs to acquire the global UMRxAsyncEngineContextListLock before
  511. the call is made.
  512. Arguments:
  513. AsyncEngineContext - The UMRX_ASYNCENGINE_CONTEXT instance which needs to be
  514. cancelled.
  515. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  516. FALSE - This cancel was initiated by the timeout
  517. mechanism.
  518. Return Value:
  519. NTSTATUS - The return status for the operation.
  520. --*/
  521. {
  522. NTSTATUS NtStatus = STATUS_SUCCESS;
  523. PWEBDAV_CONTEXT DavContext = NULL;
  524. DavDbgTrace(DAV_TRACE_DETAIL,
  525. ("%ld: MRxDAVCancelTheContext. AsyncEngineContext = %08lx\n",
  526. PsGetCurrentThreadId(), AsyncEngineContext));
  527. DavContext = (PWEBDAV_CONTEXT)AsyncEngineContext;
  528. //
  529. // We do not cancel read and wrtie operations.
  530. //
  531. switch (DavContext->EntryPoint) {
  532. case DAV_MINIRDR_ENTRY_FROM_READ:
  533. case DAV_MINIRDR_ENTRY_FROM_WRITE:
  534. goto EXIT_THE_FUNCTION;
  535. }
  536. //
  537. // We shouldn't be getting cancel I/O calls for which the MiniRedir callouts
  538. // which cannot be cancelled by the user. These can however be cancelled
  539. // by the timeout thread.
  540. //
  541. if (UserInitiatedCancel) {
  542. switch (DavContext->EntryPoint) {
  543. case DAV_MINIRDR_ENTRY_FROM_CREATESRVCALL:
  544. case DAV_MINIRDR_ENTRY_FROM_FINALIZESRVCALL:
  545. case DAV_MINIRDR_ENTRY_FROM_CLEANUPFOBX:
  546. case DAV_MINIRDR_ENTRY_FROM_FINALIZEVNETROOT:
  547. case DAV_MINIRDR_ENTRY_FROM_CREATEVNETROOT:
  548. case DAV_MINIRDR_ENTRY_FROM_CREATE:
  549. DbgPrint("MRxDAVCancelTheContext: Invalid EntryPoint = %d\n", DavContext->EntryPoint);
  550. ASSERT(FALSE);
  551. goto EXIT_THE_FUNCTION;
  552. }
  553. }
  554. switch (AsyncEngineContext->AsyncEngineContextState) {
  555. case UMRxAsyncEngineContextAllocated:
  556. case UMRxAsyncEngineContextInUserMode:
  557. AsyncEngineContext->AsyncEngineContextState = UMRxAsyncEngineContextCancelled;
  558. break;
  559. default:
  560. DavDbgTrace(DAV_TRACE_DETAIL,
  561. ("%ld: MRxDAVCancelTheContext: NOT Being Cancelled. AsyncEngineContextState: %d\n",
  562. PsGetCurrentThreadId(), AsyncEngineContext->AsyncEngineContextState));
  563. goto EXIT_THE_FUNCTION;
  564. }
  565. NtStatus = MRxDAVCompleteTheCancelledRequest(AsyncEngineContext, UserInitiatedCancel);
  566. EXIT_THE_FUNCTION:
  567. return NtStatus;
  568. }
  569. NTSTATUS
  570. MRxDAVCompleteTheCancelledRequest(
  571. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  572. BOOL UserInitiatedCancel
  573. )
  574. /*++
  575. Routine Description:
  576. This routine handles completion if the request that has been cancelled.
  577. Arguments:
  578. AsyncEngineContext - The DAV Redir's context of the operation that is being
  579. cancelled.
  580. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  581. FALSE - This cancel was initiated by the timeout
  582. mechanism.
  583. Return Value:
  584. NTSTATUS - The return status for the operation.
  585. --*/
  586. {
  587. NTSTATUS NtStatus = STATUS_SUCCESS;
  588. PWEBDAV_CONTEXT DavContext = (PWEBDAV_CONTEXT)AsyncEngineContext;
  589. DavDbgTrace(DAV_TRACE_DETAIL,
  590. ("%ld: MRxDAVCompleteTheCancelledRequest. AsyncEngineContext = %08lx\n",
  591. PsGetCurrentThreadId(), AsyncEngineContext));
  592. switch (DavContext->EntryPoint) {
  593. case DAV_MINIRDR_ENTRY_FROM_CREATESRVCALL:
  594. NtStatus = MRxDAVHandleCreateSrvCallCancellation(AsyncEngineContext, UserInitiatedCancel);
  595. goto EXIT_THE_FUNCTION;
  596. case DAV_MINIRDR_ENTRY_FROM_CREATEVNETROOT:
  597. NtStatus = MRxDAVHandleCreateVNetRootCancellation(AsyncEngineContext, UserInitiatedCancel);
  598. goto EXIT_THE_FUNCTION;
  599. case DAV_MINIRDR_ENTRY_FROM_FINALIZESRVCALL:
  600. NtStatus = MRxDAVHandleSrvCallFinalizeCancellation(AsyncEngineContext, UserInitiatedCancel);
  601. goto EXIT_THE_FUNCTION;
  602. case DAV_MINIRDR_ENTRY_FROM_FINALIZEVNETROOT:
  603. NtStatus = MRxDAVHandleFinalizeVNetRootCancellation(AsyncEngineContext, UserInitiatedCancel);
  604. goto EXIT_THE_FUNCTION;
  605. case DAV_MINIRDR_ENTRY_FROM_CREATE:
  606. NtStatus = MRxDAVHandleCreateCancellation(AsyncEngineContext, UserInitiatedCancel);
  607. goto EXIT_THE_FUNCTION;
  608. case DAV_MINIRDR_ENTRY_FROM_QUERYDIR:
  609. NtStatus = MRxDAVHandleQueryDirCancellation(AsyncEngineContext, UserInitiatedCancel);
  610. goto EXIT_THE_FUNCTION;
  611. case DAV_MINIRDR_ENTRY_FROM_CLOSESRVOPEN:
  612. NtStatus = MRxDAVHandleCloseSrvOpenCancellation(AsyncEngineContext, UserInitiatedCancel);
  613. goto EXIT_THE_FUNCTION;
  614. case DAV_MINIRDR_ENTRY_FROM_SETFILEINFORMATION:
  615. NtStatus = MRxDAVHandleSetFileInfoCancellation(AsyncEngineContext, UserInitiatedCancel);
  616. goto EXIT_THE_FUNCTION;
  617. case DAV_MINIRDR_ENTRY_FROM_CLEANUPFOBX:
  618. NtStatus = MRxDAVHandleCleanupFobxCancellation(AsyncEngineContext, UserInitiatedCancel);
  619. goto EXIT_THE_FUNCTION;
  620. case DAV_MINIRDR_ENTRY_FROM_RENAME:
  621. NtStatus = MRxDAVHandleRenameCancellation(AsyncEngineContext, UserInitiatedCancel);
  622. goto EXIT_THE_FUNCTION;
  623. case DAV_MINIRDR_ENTRY_FROM_QUERYFILEINFORMATION:
  624. NtStatus = MRxDAVHandleQueryFileInfoCancellation(AsyncEngineContext, UserInitiatedCancel);
  625. goto EXIT_THE_FUNCTION;
  626. case DAV_MINIRDR_ENTRY_FROM_REFRESHTHELOCK:
  627. NtStatus = MRxDAVHandleLockRefreshCancellation(AsyncEngineContext, UserInitiatedCancel);
  628. goto EXIT_THE_FUNCTION;
  629. default:
  630. DavDbgTrace(DAV_TRACE_ERROR,
  631. ("%ld: ERROR: MRxDAVCancelTheContext: EntryPoint: %d\n",
  632. PsGetCurrentThreadId(), DavContext->EntryPoint));
  633. goto EXIT_THE_FUNCTION;
  634. }
  635. EXIT_THE_FUNCTION:
  636. return NtStatus;
  637. }
  638. NTSTATUS
  639. MRxDAVHandleGeneralCancellation(
  640. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  641. BOOL UserInitiatedCancel
  642. )
  643. /*++
  644. Routine Description:
  645. This routine handles completion of the some requests which has been cancelled.
  646. Its called by those rotuines whose completion is straight forward and does
  647. not require any special handling.
  648. Arguments:
  649. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  650. operation.
  651. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  652. FALSE - This cancel was initiated by the timeout
  653. mechanism.
  654. Return Value:
  655. NTSTATUS - The return status for the operation.
  656. --*/
  657. {
  658. NTSTATUS NtStatus = STATUS_SUCCESS;
  659. PRX_CONTEXT RxContext = NULL;
  660. //
  661. // Only an AsyncOperation which would have returned STATUS_IO_PENDING
  662. // can be cancelled by a user.
  663. //
  664. if (UserInitiatedCancel) {
  665. ASSERT(AsyncEngineContext->AsyncOperation == TRUE);
  666. }
  667. RxContext = AsyncEngineContext->RxContext;
  668. DavDbgTrace(DAV_TRACE_DETAIL,
  669. ("%ld: MRxDAVHandleGeneralCancellation: "
  670. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  671. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  672. //
  673. // If this cancel operation was initiated by the user, we return
  674. // STATUS_CANCELLED. If it was initiated by the timeout thread, we return
  675. // STATUS_IO_TIMEOUT.
  676. //
  677. if (UserInitiatedCancel) {
  678. AsyncEngineContext->Status = STATUS_CANCELLED;
  679. } else {
  680. AsyncEngineContext->Status = STATUS_IO_TIMEOUT;
  681. }
  682. AsyncEngineContext->Information = 0;
  683. //
  684. // We take different course of action depending upon whether this request
  685. // was a synchronous or an asynchronous request.
  686. //
  687. if (AsyncEngineContext->AsyncOperation) {
  688. //
  689. // Complete the request by calling RxCompleteRequest.
  690. //
  691. RxContext->CurrentIrp->IoStatus.Status = AsyncEngineContext->Status;
  692. RxContext->CurrentIrp->IoStatus.Information = AsyncEngineContext->Information;
  693. RxCompleteRequest(RxContext, AsyncEngineContext->Status);
  694. } else {
  695. //
  696. // This was a synchronous request. There is a thread waiting for this
  697. // request to finish and be signalled. Signal the thread that is waiting
  698. // after queuing the workitem on the KQueue.
  699. //
  700. RxSignalSynchronousWaiter(RxContext);
  701. }
  702. return NtStatus;
  703. }
  704. NTSTATUS
  705. MRxDAVHandleQueryDirCancellation(
  706. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  707. BOOL UserInitiatedCancel
  708. )
  709. /*++
  710. Routine Description:
  711. This routine handles completion of the QueryDirectory request which has been
  712. cancelled.
  713. Arguments:
  714. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  715. operation.
  716. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  717. FALSE - This cancel was initiated by the timeout
  718. mechanism.
  719. Return Value:
  720. NTSTATUS - The return status for the operation.
  721. --*/
  722. {
  723. NTSTATUS NtStatus = STATUS_SUCCESS;
  724. DavDbgTrace(DAV_TRACE_ERROR,
  725. ("%ld: MRxDAVHandleQueryDirCancellation: "
  726. "AsyncEngineContext = %08lx\n",
  727. PsGetCurrentThreadId(), AsyncEngineContext));
  728. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  729. return NtStatus;
  730. }
  731. NTSTATUS
  732. MRxDAVHandleCloseSrvOpenCancellation(
  733. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  734. BOOL UserInitiatedCancel
  735. )
  736. /*++
  737. Routine Description:
  738. This routine handles completion of the CloseSrvOpen request which has been
  739. cancelled.
  740. Arguments:
  741. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  742. operation.
  743. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  744. FALSE - This cancel was initiated by the timeout
  745. mechanism.
  746. Return Value:
  747. NTSTATUS - The return status for the operation.
  748. --*/
  749. {
  750. NTSTATUS NtStatus = STATUS_SUCCESS;
  751. PMRX_FCB Fcb = AsyncEngineContext->RxContext->pRelevantSrvOpen->pFcb;
  752. PWEBDAV_FCB DavFcb = MRxDAVGetFcbExtension(Fcb);
  753. DavDbgTrace(DAV_TRACE_ERROR,
  754. ("%ld: MRxDAVHandleCloseSrvOpenCancellation: "
  755. "AsyncEngineContext = %08lx\n",
  756. PsGetCurrentThreadId(), AsyncEngineContext));
  757. //
  758. // If we had reset FileWasModified to 0 in the FormatCloseSrvOpen function,
  759. // then we need to reset it to 1.
  760. //
  761. if (DavFcb->FileModifiedBitReset) {
  762. InterlockedExchange(&(DavFcb->FileWasModified), 1);
  763. DavFcb->FileModifiedBitReset = FALSE;
  764. }
  765. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  766. return NtStatus;
  767. }
  768. NTSTATUS
  769. MRxDAVHandleSetFileInfoCancellation(
  770. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  771. BOOL UserInitiatedCancel
  772. )
  773. /*++
  774. Routine Description:
  775. This routine handles completion of the SetFileInfo request which has been
  776. cancelled.
  777. Arguments:
  778. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  779. operation.
  780. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  781. FALSE - This cancel was initiated by the timeout
  782. mechanism.
  783. Return Value:
  784. NTSTATUS - The return status for the operation.
  785. --*/
  786. {
  787. NTSTATUS NtStatus = STATUS_SUCCESS;
  788. DavDbgTrace(DAV_TRACE_ERROR,
  789. ("%ld: MRxDAVHandleSetFileInfoCancellation: "
  790. "AsyncEngineContext = %08lx\n",
  791. PsGetCurrentThreadId(), AsyncEngineContext));
  792. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  793. return NtStatus;
  794. }
  795. NTSTATUS
  796. MRxDAVHandleCreateCancellation(
  797. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  798. BOOL UserInitiatedCancel
  799. )
  800. /*++
  801. Routine Description:
  802. This routine handles completion of the Create request which has been
  803. cancelled.
  804. Arguments:
  805. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  806. operation.
  807. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  808. FALSE - This cancel was initiated by the timeout
  809. mechanism.
  810. Return Value:
  811. NTSTATUS - The return status for the operation.
  812. --*/
  813. {
  814. NTSTATUS NtStatus = STATUS_SUCCESS;
  815. DavDbgTrace(DAV_TRACE_ERROR,
  816. ("%ld: MRxDAVHandleCreateCancellation: "
  817. "AsyncEngineContext = %08lx\n",
  818. PsGetCurrentThreadId(), AsyncEngineContext));
  819. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  820. return NtStatus;
  821. }
  822. NTSTATUS
  823. MRxDAVHandleCreateSrvCallCancellation(
  824. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  825. BOOL UserInitiatedCancel
  826. )
  827. /*++
  828. Routine Description:
  829. This routine handles completion of the CreateSrvCall request which has been
  830. cancelled.
  831. Arguments:
  832. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  833. operation.
  834. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  835. FALSE - This cancel was initiated by the timeout
  836. mechanism.
  837. Return Value:
  838. NTSTATUS - The return status for the operation.
  839. --*/
  840. {
  841. NTSTATUS NtStatus = STATUS_SUCCESS;
  842. PRX_CONTEXT RxContext = NULL;
  843. PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
  844. PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
  845. PMRX_SRV_CALL SrvCall = NULL;
  846. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  847. RxContext = AsyncEngineContext->RxContext;
  848. DavDbgTrace(DAV_TRACE_ERROR,
  849. ("%ld: MRxDAVHandleCreateSrvCallCancellation: "
  850. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  851. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  852. //
  853. // A CreateSrvCall operation is always Async.
  854. //
  855. ASSERT(AsyncEngineContext->AsyncOperation == TRUE);
  856. SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
  857. ASSERT(SCCBC != NULL);
  858. SrvCalldownStructure = SCCBC->SrvCalldownStructure;
  859. ASSERT(SrvCalldownStructure != NULL);
  860. SrvCall = SrvCalldownStructure->SrvCall;
  861. ASSERT(SrvCall != NULL);
  862. //
  863. // We allocated memory for it, so it better not be NULL.
  864. //
  865. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  866. ASSERT(DavSrvCall != NULL);
  867. if (DavSrvCall->SCAlreadyInitialized) {
  868. ASSERT(RxContext->MRxContext[2] != NULL);
  869. SeDeleteClientSecurity((PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2]);
  870. RxFreePool(RxContext->MRxContext[2]);
  871. RxContext->MRxContext[2] = NULL;
  872. DavSrvCall->SCAlreadyInitialized = FALSE;
  873. }
  874. //
  875. // Set the status in the callback structure. If a CreateSrvCall is being
  876. // cancelled, this implies that it is being done by the timeout thread
  877. // since a user can never cancel a create request. Hence the status we set
  878. // is STATUS_IO_TIMEOUT.
  879. //
  880. ASSERT(UserInitiatedCancel == FALSE);
  881. SCCBC->Status = STATUS_IO_TIMEOUT;
  882. //
  883. // Call the callback function supplied by RDBSS.
  884. //
  885. SrvCalldownStructure->CallBack(SCCBC);
  886. return NtStatus;
  887. }
  888. NTSTATUS
  889. MRxDAVHandleSrvCallFinalizeCancellation(
  890. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  891. BOOL UserInitiatedCancel
  892. )
  893. /*++
  894. Routine Description:
  895. This routine handles completion of the SrvCallFinalize request which has been
  896. cancelled.
  897. Arguments:
  898. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  899. operation.
  900. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  901. FALSE - This cancel was initiated by the timeout
  902. mechanism.
  903. Return Value:
  904. NTSTATUS - The return status for the operation.
  905. --*/
  906. {
  907. NTSTATUS NtStatus = STATUS_SUCCESS;
  908. DavDbgTrace(DAV_TRACE_ERROR,
  909. ("%ld: MRxDAVHandleSrvCallFinalizeCancellation: "
  910. "AsyncEngineContext = %08lx\n",
  911. PsGetCurrentThreadId(), AsyncEngineContext));
  912. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  913. return NtStatus;
  914. }
  915. NTSTATUS
  916. MRxDAVHandleCreateVNetRootCancellation(
  917. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  918. BOOL UserInitiatedCancel
  919. )
  920. /*++
  921. Routine Description:
  922. This routine handles completion of the CreateVNetRoot request which has been
  923. cancelled.
  924. Arguments:
  925. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  926. operation.
  927. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  928. FALSE - This cancel was initiated by the timeout
  929. mechanism.
  930. Return Value:
  931. NTSTATUS - The return status for the operation.
  932. --*/
  933. {
  934. NTSTATUS NtStatus = STATUS_SUCCESS;
  935. PRX_CONTEXT RxContext = NULL;
  936. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  937. PMRX_V_NET_ROOT VNetRoot = NULL;
  938. RxContext = AsyncEngineContext->RxContext;
  939. DavDbgTrace(DAV_TRACE_ERROR,
  940. ("%ld: MRxDAVHandleCreateVNetRootCancellation: "
  941. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  942. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  943. //
  944. // The VNetRoot pointer is stored in the MRxContext[1] pointer of the
  945. // RxContext structure. This is done in the MRxDAVCreateVNetRoot
  946. // function.
  947. //
  948. VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
  949. DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
  950. ASSERT(DavVNetRoot != NULL);
  951. DavVNetRoot->createVNetRootUnSuccessful = TRUE;
  952. //
  953. // Set the status in the AsyncEngineContext. If a CreateSrvCall is being
  954. // cancelled, this implies that it is being done by the timeout thread
  955. // since a user can never cancel a create request. Hence the status we set
  956. // is STATUS_IO_TIMEOUT.
  957. //
  958. ASSERT(UserInitiatedCancel == FALSE);
  959. AsyncEngineContext->Status = STATUS_IO_TIMEOUT;
  960. //
  961. // This was a synchronous request. There is a thread waiting for this
  962. // request to finish and be signalled. Signal the thread that is waiting
  963. // after queuing the workitem on the KQueue.
  964. //
  965. ASSERT(AsyncEngineContext->AsyncOperation == FALSE);
  966. RxSignalSynchronousWaiter(RxContext);
  967. return NtStatus;
  968. }
  969. NTSTATUS
  970. MRxDAVHandleFinalizeVNetRootCancellation(
  971. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  972. BOOL UserInitiatedCancel
  973. )
  974. /*++
  975. Routine Description:
  976. This routine handles completion of the FinalizeVNetRoot request which has
  977. been cancelled.
  978. Arguments:
  979. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  980. operation.
  981. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  982. FALSE - This cancel was initiated by the timeout
  983. mechanism.
  984. Return Value:
  985. NTSTATUS - The return status for the operation.
  986. --*/
  987. {
  988. NTSTATUS NtStatus = STATUS_SUCCESS;
  989. DavDbgTrace(DAV_TRACE_ERROR,
  990. ("%ld: MRxDAVHandleFinalizeVNetRootCancellation: "
  991. "AsyncEngineContext = %08lx\n",
  992. PsGetCurrentThreadId(), AsyncEngineContext));
  993. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  994. return NtStatus;
  995. }
  996. NTSTATUS
  997. MRxDAVHandleCleanupFobxCancellation(
  998. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  999. BOOL UserInitiatedCancel
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine handles completion of the CleanupFobx request which has been
  1004. cancelled.
  1005. Arguments:
  1006. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  1007. operation.
  1008. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  1009. FALSE - This cancel was initiated by the timeout
  1010. mechanism.
  1011. Return Value:
  1012. NTSTATUS - The return status for the operation.
  1013. --*/
  1014. {
  1015. NTSTATUS NtStatus = STATUS_SUCCESS;
  1016. DavDbgTrace(DAV_TRACE_ERROR,
  1017. ("%ld: MRxDAVHandleCleanupFobxCancellation: "
  1018. "AsyncEngineContext = %08lx\n",
  1019. PsGetCurrentThreadId(), AsyncEngineContext));
  1020. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  1021. return NtStatus;
  1022. }
  1023. NTSTATUS
  1024. MRxDAVHandleRenameCancellation(
  1025. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  1026. BOOL UserInitiatedCancel
  1027. )
  1028. /*++
  1029. Routine Description:
  1030. This routine handles completion of the Rename request which has been
  1031. cancelled.
  1032. Arguments:
  1033. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  1034. operation.
  1035. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  1036. FALSE - This cancel was initiated by the timeout
  1037. mechanism.
  1038. Return Value:
  1039. NTSTATUS - The return status for the operation.
  1040. --*/
  1041. {
  1042. NTSTATUS NtStatus = STATUS_SUCCESS;
  1043. DavDbgTrace(DAV_TRACE_ERROR,
  1044. ("%ld: MRxDAVHandleRenameCancellation: "
  1045. "AsyncEngineContext = %08lx\n",
  1046. PsGetCurrentThreadId(), AsyncEngineContext));
  1047. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  1048. return NtStatus;
  1049. }
  1050. NTSTATUS
  1051. MRxDAVHandleQueryFileInfoCancellation(
  1052. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  1053. BOOL UserInitiatedCancel
  1054. )
  1055. /*++
  1056. Routine Description:
  1057. This routine handles completion of the QueryFileInfo request which has been
  1058. cancelled.
  1059. Arguments:
  1060. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  1061. operation.
  1062. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  1063. FALSE - This cancel was initiated by the timeout
  1064. mechanism.
  1065. Return Value:
  1066. NTSTATUS - The return status for the operation.
  1067. --*/
  1068. {
  1069. NTSTATUS NtStatus = STATUS_SUCCESS;
  1070. DavDbgTrace(DAV_TRACE_ERROR,
  1071. ("%ld: MRxDAVHandleQueryFileInfoCancellation: "
  1072. "AsyncEngineContext = %08lx\n",
  1073. PsGetCurrentThreadId(), AsyncEngineContext));
  1074. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  1075. return NtStatus;
  1076. }
  1077. NTSTATUS
  1078. MRxDAVHandleLockRefreshCancellation(
  1079. PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
  1080. BOOL UserInitiatedCancel
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. This routine handles completion of the QueryFileInfo request which has been
  1085. cancelled.
  1086. Arguments:
  1087. AsyncEngineContext - The DAV Redir's context describing the CreateSrvCall
  1088. operation.
  1089. UserInitiatedCancel - TRUE - This cancel was initiated by a user request.
  1090. FALSE - This cancel was initiated by the timeout
  1091. mechanism.
  1092. Return Value:
  1093. NTSTATUS - The return status for the operation.
  1094. --*/
  1095. {
  1096. NTSTATUS NtStatus = STATUS_SUCCESS;
  1097. DavDbgTrace(DAV_TRACE_ERROR,
  1098. ("%ld: MRxDAVHandleLockRefreshCancellation: "
  1099. "AsyncEngineContext = %08lx\n",
  1100. PsGetCurrentThreadId(), AsyncEngineContext));
  1101. NtStatus = MRxDAVHandleGeneralCancellation(AsyncEngineContext, UserInitiatedCancel);
  1102. return NtStatus;
  1103. }
  1104. VOID
  1105. MRxDAVRefreshTheServerLocks(
  1106. PVOID DummyContext
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This routine is called by the timer thread to refresh the LOCKs that have
  1111. been taken on various files which are shared on different servers. The
  1112. LOCKs are granted by the server for a limited period of time and if the
  1113. client wants to hold the LOCK for a longer period than that, it needs to
  1114. send a refresh request to the server.
  1115. Arguments:
  1116. DummyContext - A dummy context that is supplied.
  1117. Return Value:
  1118. None.
  1119. --*/
  1120. {
  1121. NTSTATUS NtStatus = STATUS_SUCCESS;
  1122. PLIST_ENTRY TokenListEntry = NULL;
  1123. PWEBDAV_LOCK_TOKEN_ENTRY LockTokenEntry = NULL;
  1124. BOOL lockAcquired = FALSE;
  1125. LARGE_INTEGER CurrentSystemTickCount, TickCountDifference;
  1126. LARGE_INTEGER LockTimeoutValueInTickCount;
  1127. PRX_CONTEXT RxContext = NULL;
  1128. PRDBSS_DEVICE_OBJECT RxDeviceObject = (PRDBSS_DEVICE_OBJECT)MRxDAVDeviceObject;
  1129. ExAcquireResourceExclusiveLite(&(LockTokenEntryListLock), TRUE);
  1130. lockAcquired = TRUE;
  1131. TokenListEntry = LockTokenEntryList.Flink;
  1132. while ( TokenListEntry != &(LockTokenEntryList) ) {
  1133. //
  1134. // Get the pointer to the WEBDAV_LOCK_TOKEN_ENTRY structure.
  1135. //
  1136. LockTokenEntry = CONTAINING_RECORD(TokenListEntry,
  1137. WEBDAV_LOCK_TOKEN_ENTRY,
  1138. listEntry);
  1139. TokenListEntry = TokenListEntry->Flink;
  1140. //
  1141. // An RxContext is required for a request to be reflected up.
  1142. //
  1143. RxContext = RxCreateRxContext(NULL, RxDeviceObject, 0);
  1144. if (RxContext == NULL) {
  1145. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1146. DavDbgTrace(DAV_TRACE_ERROR,
  1147. ("%ld: MRxDAVRefreshTheServerLocks/RxCreateRxContext: "
  1148. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  1149. goto EXIT_THE_FUNCTION;
  1150. }
  1151. //
  1152. // Calculate the timeout value in TickCount (100 nano seconds) using
  1153. // the timeout value in seconds). Step1 below calculates the number of
  1154. // ticks that happen in one second. Step2 below calculates the number
  1155. // of ticks in LockTimeoutValueInSec.
  1156. //
  1157. LockTimeoutValueInTickCount.QuadPart = ( (1000 * 1000 * 10) / KeQueryTimeIncrement() );
  1158. LockTimeoutValueInTickCount.QuadPart *= LockTokenEntry->LockTimeOutValueInSec;
  1159. KeQueryTickCount( &(CurrentSystemTickCount) );
  1160. //
  1161. // Get the time elapsed (in system tick counts) since the time this
  1162. // LockTokenEntry was created.
  1163. //
  1164. TickCountDifference.QuadPart = (CurrentSystemTickCount.QuadPart - LockTokenEntry->CreationTimeInTickCount.QuadPart);
  1165. //
  1166. // If the time difference betweeen the current time and the last time
  1167. // this LOCK was refreshed is greater than LockTimeOut/2, we need to
  1168. // refresh this LOCK. To refresh the LOCK, we need to go to the usermode
  1169. // to send the request. Also, we only refresh this lock if the value of
  1170. // LockTokenEntry->ShouldThisEntryBeRefreshed is TRUE.
  1171. //
  1172. if ( LockTokenEntry->ShouldThisEntryBeRefreshed &&
  1173. TickCountDifference.QuadPart > (LockTimeoutValueInTickCount.QuadPart / 2) ) {
  1174. //
  1175. // We need to store the LockTokenEntry in the RxContext since it
  1176. // will be needed to impersonate the client and refresh the LOCK.
  1177. //
  1178. RxContext->MRxContext[1] = LockTokenEntry;
  1179. NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
  1180. SIZEOF_DAV_SPECIFIC_CONTEXT,
  1181. MRxDAVFormatTheDAVContext,
  1182. DAV_MINIRDR_ENTRY_FROM_REFRESHTHELOCK,
  1183. MRxDAVRefreshTheServerLocksContinuation,
  1184. "MRxDAVRefreshTheServerLocks");
  1185. if (NtStatus != ERROR_SUCCESS) {
  1186. //
  1187. // Even if we fail to refresh one LOCK we continue to refresh
  1188. // the remaining LOCKs in the LockTokenEntryList.
  1189. //
  1190. DavDbgTrace(DAV_TRACE_ERROR,
  1191. ("%ld: MRxDAVRefreshTheServerLocks/UMRxAsyncEngOuterWrapper: "
  1192. "LockTokenEntry = %08lx, NtStatus = %08lx.\n",
  1193. PsGetCurrentThreadId(), LockTokenEntry, NtStatus));
  1194. }
  1195. }
  1196. //
  1197. // We take the reference out on the RxContext we allocated above. If
  1198. // NtStatus is not STATUS_CANCELLED, this also lands up freeing the
  1199. // RxContext since this would be the last reference on the RxContext.
  1200. // If NtStatus is STATUS_CANCELLED then the AsyncEngineContext associated
  1201. // with this RxContext might have a reference on this RxContext (if the
  1202. // request hasn't come back from the usermode). In such a scenario, the
  1203. // RxContext is freed up when request comes back from the usermode.
  1204. //
  1205. RxDereferenceAndDeleteRxContext(RxContext);
  1206. }
  1207. EXIT_THE_FUNCTION:
  1208. if (lockAcquired) {
  1209. ExReleaseResourceLite(&(LockTokenEntryListLock));
  1210. lockAcquired = FALSE;
  1211. }
  1212. //
  1213. // Before we exit, we need to set QueueLockRefreshWorkItem to TRUE so
  1214. // that a new WorkItem can get queued to refresh the active locks.
  1215. //
  1216. ExAcquireResourceExclusiveLite(&(QueueLockRefreshWorkItemLock), TRUE);
  1217. QueueLockRefreshWorkItem = TRUE;
  1218. ExReleaseResourceLite(&(QueueLockRefreshWorkItemLock));
  1219. return;
  1220. }
  1221. NTSTATUS
  1222. MRxDAVRefreshTheServerLocksContinuation(
  1223. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. This is the continuation routine which refreshes a LOCK.
  1228. Arguments:
  1229. AsyncEngineContext - The Reflectors context.
  1230. RxContext - The RDBSS context.
  1231. Return Value:
  1232. RXSTATUS - The return status for the operation
  1233. --*/
  1234. {
  1235. NTSTATUS NtStatus = STATUS_SUCCESS;
  1236. PAGED_CODE();
  1237. DavDbgTrace(DAV_TRACE_DETAIL,
  1238. ("%ld: Entering MRxDAVRefreshTheServerLocksContinuation\n",
  1239. PsGetCurrentThreadId()));
  1240. DavDbgTrace(DAV_TRACE_CONTEXT,
  1241. ("%ld: MRxDAVRefreshTheServerLocksContinuation: "
  1242. "AsyncEngineContext: %08lx, RxContext: %08lx\n",
  1243. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1244. //
  1245. // Try usermode.
  1246. //
  1247. NtStatus = UMRxSubmitAsyncEngUserModeRequest(
  1248. UMRX_ASYNCENGINE_ARGUMENTS,
  1249. MRxDAVFormatUserModeRefreshTheServerLockRequest,
  1250. MRxDAVPrecompleteUserModeRefreshTheServerLockRequest
  1251. );
  1252. DavDbgTrace(DAV_TRACE_DETAIL,
  1253. ("%ld: Leaving MRxDAVFinalizeSrvCallContinuation with NtStatus"
  1254. " = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  1255. return NtStatus;
  1256. }
  1257. NTSTATUS
  1258. MRxDAVFormatUserModeRefreshTheServerLockRequest(
  1259. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  1260. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  1261. IN ULONG WorkItemLength,
  1262. OUT PULONG_PTR ReturnedLength
  1263. )
  1264. /*++
  1265. Routine Description:
  1266. This routine formats the LOCK refresh request being sent to the user mode
  1267. for processing.
  1268. Arguments:
  1269. RxContext - The RDBSS context.
  1270. AsyncEngineContext - The reflctor's context.
  1271. WorkItem - The work item buffer.
  1272. WorkItemLength - The length of the work item buffer.
  1273. ReturnedLength -
  1274. Return Value:
  1275. STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
  1276. --*/
  1277. {
  1278. NTSTATUS NtStatus = STATUS_SUCCESS;
  1279. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  1280. PWEBDAV_LOCK_TOKEN_ENTRY LockTokenEntry = NULL;
  1281. PDAV_USERMODE_LOCKREFRESH_REQUEST LockRefreshRequest = NULL;
  1282. PBYTE ServerName = NULL, PathName = NULL, OpaqueLockToken = NULL;
  1283. ULONG ServerNameLengthInBytes = 0, PathNameLengthInBytes = 0, OpaqueLockTokenLengthInBytes = 0;
  1284. PAGED_CODE();
  1285. DavDbgTrace(DAV_TRACE_DETAIL,
  1286. ("%ld: Entering MRxDAVFormatUserModeRefreshTheServerLockRequest.\n",
  1287. PsGetCurrentThreadId()));
  1288. DavDbgTrace(DAV_TRACE_CONTEXT,
  1289. ("%ld: MRxDAVFormatUserModeRefreshTheServerLockRequest: "
  1290. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  1291. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1292. LockRefreshRequest = &(DavWorkItem->LockRefreshRequest);
  1293. //
  1294. // LockTokenEntry was set to MRxContext[1] in the MRxDAVRefreshTheServerLocks
  1295. // routine.
  1296. //
  1297. LockTokenEntry = (PWEBDAV_LOCK_TOKEN_ENTRY)RxContext->MRxContext[1];
  1298. DavWorkItem->WorkItemType = UserModeLockRefresh;
  1299. //
  1300. // Copy the ServerName.
  1301. //
  1302. ServerNameLengthInBytes = (1 + wcslen(LockTokenEntry->ServerName)) * sizeof(WCHAR);
  1303. ServerName = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  1304. ServerNameLengthInBytes);
  1305. if (ServerName == NULL) {
  1306. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1307. DavDbgTrace(DAV_TRACE_ERROR,
  1308. ("ld: MRxDAVFormatUserModeRefreshTheServerLockRequest/"
  1309. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  1310. PsGetCurrentThreadId(), NtStatus));
  1311. goto EXIT_THE_FUNCTION;
  1312. }
  1313. LockRefreshRequest->ServerName = (PWCHAR)ServerName;
  1314. wcscpy(LockRefreshRequest->ServerName, LockTokenEntry->ServerName);
  1315. //
  1316. // Copy the PathName.
  1317. //
  1318. PathNameLengthInBytes = (1 + wcslen(LockTokenEntry->PathName)) * sizeof(WCHAR);
  1319. PathName = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  1320. PathNameLengthInBytes);
  1321. if (PathName == NULL) {
  1322. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1323. DavDbgTrace(DAV_TRACE_ERROR,
  1324. ("ld: MRxDAVFormatUserModeRefreshTheServerLockRequest/"
  1325. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  1326. PsGetCurrentThreadId(), NtStatus));
  1327. goto EXIT_THE_FUNCTION;
  1328. }
  1329. LockRefreshRequest->PathName = (PWCHAR)PathName;
  1330. wcscpy(LockRefreshRequest->PathName, LockTokenEntry->PathName);
  1331. //
  1332. // Copy the OpaqueLockToken.
  1333. //
  1334. OpaqueLockTokenLengthInBytes = (1 + wcslen(LockTokenEntry->OpaqueLockToken)) * sizeof(WCHAR);
  1335. OpaqueLockToken = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  1336. OpaqueLockTokenLengthInBytes);
  1337. if (OpaqueLockToken == NULL) {
  1338. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1339. DavDbgTrace(DAV_TRACE_ERROR,
  1340. ("ld: MRxDAVFormatUserModeRefreshTheServerLockRequest/"
  1341. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  1342. PsGetCurrentThreadId(), NtStatus));
  1343. goto EXIT_THE_FUNCTION;
  1344. }
  1345. LockRefreshRequest->OpaqueLockToken = (PWCHAR)OpaqueLockToken;
  1346. wcscpy(LockRefreshRequest->OpaqueLockToken, LockTokenEntry->OpaqueLockToken);
  1347. LockRefreshRequest->ServerID = LockTokenEntry->ServerID;
  1348. LockRefreshRequest->LogonID.LowPart = LockTokenEntry->LogonID.LowPart;
  1349. LockRefreshRequest->LogonID.HighPart = LockTokenEntry->LogonID.HighPart;
  1350. //
  1351. // Impersonate the client who initiated the request. If we fail to
  1352. // impersonate, tough luck.
  1353. //
  1354. NtStatus = UMRxImpersonateClient(LockTokenEntry->SecurityClientContext, WorkItemHeader);
  1355. if (!NT_SUCCESS(NtStatus)) {
  1356. DavDbgTrace(DAV_TRACE_ERROR,
  1357. ("%ld: ERROR: MRxDAVFormatUserModeRefreshTheServerLockRequest/"
  1358. "UMRxImpersonateClient. NtStatus = %08lx.\n",
  1359. PsGetCurrentThreadId(), NtStatus));
  1360. goto EXIT_THE_FUNCTION;
  1361. }
  1362. EXIT_THE_FUNCTION:
  1363. DavDbgTrace(DAV_TRACE_DETAIL,
  1364. ("%ld: Leaving MRxDAVFormatUserModeRefreshTheServerLockRequest "
  1365. "with NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  1366. return NtStatus;
  1367. }
  1368. BOOL
  1369. MRxDAVPrecompleteUserModeRefreshTheServerLockRequest(
  1370. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  1371. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  1372. ULONG WorkItemLength,
  1373. BOOL OperationCancelled
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. The precompletion routine for the LOCK refresh request.
  1378. Arguments:
  1379. RxContext - The RDBSS context.
  1380. AsyncEngineContext - The reflctor's context.
  1381. WorkItem - The work item buffer.
  1382. WorkItemLength - The length of the work item buffer.
  1383. OperationCancelled - TRUE if this operation was cancelled by the user.
  1384. Return Value:
  1385. TRUE - UMRxAsyncEngineCalldownIrpCompletion is called by the function
  1386. UMRxCompleteUserModeRequest after we return.
  1387. --*/
  1388. {
  1389. NTSTATUS NtStatus = STATUS_SUCCESS;
  1390. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  1391. PDAV_USERMODE_LOCKREFRESH_REQUEST LockRefreshRequest = NULL;
  1392. PDAV_USERMODE_LOCKREFRESH_RESPONSE LockRefreshResponse = NULL;
  1393. PWEBDAV_LOCK_TOKEN_ENTRY LockTokenEntry = NULL;
  1394. PAGED_CODE();
  1395. DavDbgTrace(DAV_TRACE_DETAIL,
  1396. ("%ld: Entering MRxDAVPrecompleteUserModeRefreshTheServerLockRequest\n",
  1397. PsGetCurrentThreadId()));
  1398. DavDbgTrace(DAV_TRACE_CONTEXT,
  1399. ("%ld: MRxDAVPrecompleteUserModeRefreshTheServerLockRequest: "
  1400. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  1401. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1402. LockRefreshRequest = &(DavWorkItem->LockRefreshRequest);
  1403. LockRefreshResponse = &(DavWorkItem->LockRefreshResponse);
  1404. if (OperationCancelled) {
  1405. DavDbgTrace(DAV_TRACE_ERROR,
  1406. ("%ld: MRxDAVPrecompleteUserModeRefreshTheServerLockRequest: Operation Cancelled. "
  1407. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  1408. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1409. }
  1410. //
  1411. // We need to free up the heap we allocated in the format routine.
  1412. //
  1413. if (LockRefreshRequest->ServerName != NULL) {
  1414. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  1415. (PBYTE)LockRefreshRequest->ServerName);
  1416. if (NtStatus != STATUS_SUCCESS) {
  1417. DavDbgTrace(DAV_TRACE_ERROR,
  1418. ("%ld: ERROR: MRxDAVPrecompleteUserModeRefreshTheServerLockRequest/"
  1419. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  1420. PsGetCurrentThreadId(), NtStatus));
  1421. }
  1422. }
  1423. if (LockRefreshRequest->PathName != NULL) {
  1424. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  1425. (PBYTE)LockRefreshRequest->PathName);
  1426. if (NtStatus != STATUS_SUCCESS) {
  1427. DavDbgTrace(DAV_TRACE_ERROR,
  1428. ("%ld: ERROR: MRxDAVPrecompleteUserModeRefreshTheServerLockRequest/"
  1429. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  1430. PsGetCurrentThreadId(), NtStatus));
  1431. }
  1432. }
  1433. if (LockRefreshRequest->OpaqueLockToken != NULL) {
  1434. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  1435. (PBYTE)LockRefreshRequest->OpaqueLockToken);
  1436. if (NtStatus != STATUS_SUCCESS) {
  1437. DavDbgTrace(DAV_TRACE_ERROR,
  1438. ("%ld: ERROR: MRxDAVPrecompleteUserModeRefreshTheServerLockRequest/"
  1439. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  1440. PsGetCurrentThreadId(), NtStatus));
  1441. }
  1442. }
  1443. if (!OperationCancelled) {
  1444. //
  1445. // LockTokenEntry was set to MRxContext[1] in the MRxDAVRefreshTheServerLocks
  1446. // routine.
  1447. //
  1448. LockTokenEntry = (PWEBDAV_LOCK_TOKEN_ENTRY)RxContext->MRxContext[1];
  1449. //
  1450. // Get the new timeout value returned by the server.
  1451. //
  1452. LockTokenEntry->LockTimeOutValueInSec = LockRefreshResponse->NewTimeOutInSec;
  1453. //
  1454. // Set the current system time as the new creation time of the entry.
  1455. //
  1456. KeQueryTickCount( &(LockTokenEntry->CreationTimeInTickCount) );
  1457. }
  1458. DavDbgTrace(DAV_TRACE_DETAIL,
  1459. ("%ld: Leaving MRxDAVPrecompleteUserModeRefreshTheServerLockRequest\n",
  1460. PsGetCurrentThreadId()));
  1461. return TRUE;
  1462. }